def make_node(self, cls, element): node = cls() having_block_node = cls in HAVING_BLOCK_NODE if element.text and element.text != "\n": text = self.unescape_char(element.text) if HTML_PLACEHOLDER_RE.search(text): node += nodes.raw(format='html', text=self.unescape_char(text, rawHtml=True)) elif having_block_node: node += nodes.paragraph(text=text) else: node += nodes.Text(text) for child in element: subnode = self.visit(child) if having_block_node and isinstance(subnode, INLINE_NODES): all_nodes_is_in_paragraph = True if len(node) == 0: node += nodes.paragraph() node[0] += subnode else: all_nodes_is_in_paragraph = False node += subnode if child.tail and child.tail != "\n": tail = self.unescape_char(child.tail) if HTML_PLACEHOLDER_RE.search(tail): node += nodes.raw(format='html', text=tail) elif all_nodes_is_in_paragraph: node[0] += nodes.Text(tail) elif having_block_node: node += nodes.paragraph(text=tail) else: node += nodes.Text(tail) return node
def run(self): if self.arguments[0] == "blog-responsive-sidebar": return [nodes.raw('', """<div class="blog-ad-container-skyscraper"> <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <!-- blog responsive sidebar --> <ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-1959826171259933" data-ad-slot="9751446737" data-ad-format="auto"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script> </div>""", format='html')] else: return [nodes.raw('', """<div class="blog-ad-container-banner"> <script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <!-- blog responsive banner --> <ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-1959826171259933" data-ad-slot="8774241139" data-ad-format="auto"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script> </div>""", format='html')]
def run(self): """Run the gist directive.""" if 'https://' in self.arguments[0]: gistID = self.arguments[0].split('/')[-1].strip() else: gistID = self.arguments[0].strip() embedHTML = "" rawGist = "" if 'file' in self.options: filename = self.options['file'] rawGist = (self.get_raw_gist_with_filename(gistID, filename)) embedHTML = ('<script src="https://gist.github.com/{0}.js' '?file={1}"></script>').format(gistID, filename) else: rawGist = (self.get_raw_gist(gistID)) embedHTML = ('<script src="https://gist.github.com/{0}.js">' '</script>').format(gistID) reqnode = nodes.literal_block('', rawGist) return [nodes.raw('', embedHTML, format='html'), nodes.raw('', '<noscript>', format='html'), reqnode, nodes.raw('', '</noscript>', format='html')]
def run(self): """Run the directive.""" if pygal is None: msg = req_missing(['pygal'], 'use the Chart directive', optional=True) return [nodes.raw('', '<div class="text-error">{0}</div>'.format(msg), format='html')] options = {} if 'style' in self.options: style_name = self.options.pop('style') else: style_name = 'BlueStyle' if '(' in style_name: # Parametric style style = eval('pygal.style.' + style_name) else: style = getattr(pygal.style, style_name) for k, v in self.options.items(): options[k] = literal_eval(v) chart = getattr(pygal, self.arguments[0])(style=style) chart.config(**options) for line in self.content: label, series = literal_eval('({0})'.format(line)) chart.add(label, series) data = chart.render().decode('utf8') if _site and _site.invariant: import re data = re.sub('id="chart-[a-f0-9\-]+"', 'id="chart-foobar"', data) data = re.sub('#chart-[a-f0-9\-]+', '#chart-foobar', data) return [nodes.raw('', data, format='html')]
def run(self): """ Restructured text extension for inserting embedded AVs with show/hide button """ self.options['address'] = self.arguments[0] embed = embedlocal(self.arguments[0]) self.options['av_address'] = embed[0] self.options['width'] = embed[1] self.options['height'] = embed[2] self.options['div_id'] = random.randint(1,1000) if 'showbutton' in self.options: divID = "Example%s"%self.options['div_id'] #random.randint(1,1000) self.options['divID'] = divID if self.options['showbutton'] == "show": res = SHOW % (self.options) res += HIDE % (self.options) res += CODE1 % (self.options) res += CODE % (self.options) return [nodes.raw('', res, format='html')] else: res = SHOW % (self.options) res += HIDE % (self.options) return [nodes.raw('', res, format='html')] else: res = CODE % self.options return [nodes.raw('', res, format='html')]
def run(self): if pygal is None: msg = req_missing(['pygal'], 'use the Chart directive', optional=True) return [nodes.raw('', '<div class="text-error">{0}</div>'.format(msg), format='html')] options = {} if 'style' in self.options: style_name = self.options.pop('style') else: style_name = 'LightStyle' if 'fill' not in self.options: self.options["fill"] = "red" if '(' in style_name: # Parametric style style = eval('pygal.style.' + style_name) else: style = getattr(pygal.style, style_name) for k, v in self.options.items(): options[k] = literal_eval(v) chart = getattr(pygal, self.arguments[0])(style=style) chart.config(**options) for line in self.content: label, series = literal_eval('({0})'.format(line)) chart.add(label, series) data = chart.render().decode('utf8') assert data.startswith("<?xml version='1.0' encoding='utf-8'?>") data = data[71-33:] return [nodes.raw('', data, format='html')]
def plan_directive(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """Setup for tags relating to a plan file.""" global CURRENT_PLAN_ID global CURRENT_PLAN_SETTINGS if not CURRENT_PLAN_ID: raw_node = nodes.raw( '', '<div id="plan-container"></div>' '<script type="text/javascript" src="js/plan.js"></script>' '<hr class="clear" />', format='html' ) else: raw_node = nodes.raw('', '', format='html') content = '\n'.join(content) if content: CURRENT_PLAN_SETTINGS = decode_json(content) else: CURRENT_PLAN_SETTINGS = {} CURRENT_PLAN_ID = arguments[0] return [raw_node]
def run(self): self.assert_has_content() text = '\n'.join(self.content) parsed = highlight(text, PythonLexer(), HtmlFormatter()) result = [nodes.raw('', parsed, format='html')] if True: # If we want a snapshot - this should check the 'snapshot argument'# fn = '{}.png'.format(sha(text).hexdigest()) env = self.state.document.settings.env rel_filename, filename = env.relfn2path(fn) outfn = os.path.join(env.app.builder.outdir, '_static', rel_filename) ensuredir(os.path.dirname(outfn)) script_to_render = BOT_HEADER + text try: subprocess.call(['sbot', '-o', '%s' % outfn, script_to_render]) except Exception, e: raise ShoebotError(str(e)) # TODO - Support other output formats image_node = nodes.raw('', html_img_tag(rel_filename), format='html') result.insert(0,image_node)
def run(self): url = self.arguments[0].strip() title = "" cardChrome = 0 if 'title' in self.options: title = self.options['title'] if 'card-chrome' in self.options: cardChrome = self.options['card-chrome'] linkHTML = "<a class='embedly-card' data-card-chrome='{2}' href='{0}'>{1}</a>".format(url, title, cardChrome) scriptHTML = """ <script> !function(a){ var b="embedly-platform",c="script"; if(!a.getElementById(b)){ var d=a.createElement(c); d.id=b; d.src=("https:"===document.location.protocol?"https":"http")+"://cdn.embedly.com/widgets/platform.js"; var e=document.getElementsByTagName(c)[0];e.parentNode.insertBefore(d,e)} }(document); </script> """ return [nodes.raw('', linkHTML, format='html'), nodes.raw('', scriptHTML, format='html')]
def run(self): prefix = raw('', '\\par\\begin{samepage}', format='latex') suffix = raw('', '\\end{samepage}\\par', format='latex') text = '\n'.join(self.content) content_node = compound(rawsource=text) self.state.nested_parse(self.content, self.content_offset, content_node) return [prefix, content_node, suffix]
def ref_role(role, rawtext, text, lineno, inliner, options={}, content=[]): """ ---------------------- Docutils role: ``ref`` ---------------------- Inserts a hyperlink reference to a figure or table with a custom label. Example ------- :: :ref:`image-filename.png` This will hyperlink to:: .. fig:: Some image here :image: image-filename.png :scale: 0.75 or :: :fig:`trapezoid` This will hyperlink to:: .. fig:: Sample Trapezoid :position: side :label: trapezoid \begin{tikzpicture} \draw [fill=black!10] (-1,0.7) -- (1,0.7) -- (0.7,-0.7) -- (-0.7,-0.7) -- cycle; \end{tikzpicture} Notes ----- * Works only for ``latex`` writer ... for now :) """ ref = nodes.make_id(text) if role in ['fig', 'tbl']: ref = role + ':' + ref t = dict() t['latex'] = r'\hyperref[%s]{\ref*{%s}}' % (ref, ref) t['html'] = r'<a href="#%s">[link]</a>' % (ref,) node_list = [ nodes.raw(text=t['latex'], format='latex'), nodes.raw(text=t['html'], format='html') ] return node_list, []
def run(self): if 'https://' in self.arguments[0]: gistID = self.arguments[0].split('/')[-1].strip() else: gistID = self.arguments[0].strip() embedHTML = "" rawGist = "" if 'file' in self.options: filename = self.options['file'] if requests is not None: rawGist = (self.get_raw_gist_with_filename(gistID, filename)) embedHTML = ('<script src="https://gist.github.com/{0}.js' '?file={1}"></script>').format(gistID, filename) else: if requests is not None: rawGist = (self.get_raw_gist(gistID)) embedHTML = ('<script src="https://gist.github.com/{0}.js">' '</script>').format(gistID) if requests is None: reqnode = nodes.raw( '', req_missing('requests', 'have inline gist source', optional=True), format='html') else: reqnode = nodes.literal_block('', rawGist) return [nodes.raw('', embedHTML, format='html'), nodes.raw('', '<noscript>', format='html'), reqnode, nodes.raw('', '</noscript>', format='html')]
def math(role, rawtext, text, lineno, inliner, options={}, content=[]): # Otherwise the backslashes do quite a mess there i = rawtext.find('`') text = rawtext.split('`')[1] # Fallback rendering as code requested if settings['M_MATH_RENDER_AS_CODE']: set_classes(options) classes = [] if 'classes' in options: classes += options['classes'] del options['classes'] content = nodes.raw('', html.escape(utils.unescape(text)), format='html') node = nodes.literal(rawtext, '', **options) node.append(content) return [node], [] # Apply classes to the <svg> element instead of some outer <span> set_classes(options) classes = 'm-math' if 'classes' in options: classes += ' ' + ' '.join(options['classes']) del options['classes'] depth, svg = latex2svgextra.fetch_cached_or_render("$" + text + "$") attribs = ' class="{}"'.format(classes) node = nodes.raw(rawtext, latex2svgextra.patch(text, svg, depth, attribs), format='html', **options) return [node], []
def run(self): videoID = self.arguments[0].strip() width = 420 height = 315 domain = 'www.youtube.com' if 'width' in self.options: width = self.options['width'] if 'height' in self.options: height = self.options['height'] if 'nocookie' in self.options and self.options['nocookie'] == 'yes': domain = 'www.youtube-nocookie.com' url = 'https://{}/embed/{}'.format(domain, videoID) div_block = '<div class="youtube">' embed_block = '<iframe width="{}" height="{}" src="{}">'\ '</iframe>'.format(width, height, url) return [ nodes.raw('', div_block, format='html'), nodes.raw('', embed_block, format='html'), nodes.raw('', '</div>', format='html')]
def run(self): if requests is None: msg = ( 'To use the gist directive, you need to install the ' '"requests" package.\n' ) utils.LOGGER.warn(msg) return [nodes.raw('', '<div class="text-error">{0}</div>'.format(msg), format='html')] gistID = self.arguments[0].strip() embedHTML = "" rawGist = "" if 'file' in self.options: filename = self.options['file'] rawGist = (self.get_raw_gist_with_filename(gistID, filename)) embedHTML = ('<script src="https://gist.github.com/{0}.js' '?file={1}"></script>').format(gistID, filename) else: rawGist = (self.get_raw_gist(gistID)) embedHTML = ('<script src="https://gist.github.com/{0}.js">' '</script>').format(gistID) return [nodes.raw('', embedHTML, format='html'), nodes.raw('', '<noscript>', format='html'), nodes.literal_block('', rawGist), nodes.raw('', '</noscript>', format='html')]
def run(self): if micawber is None: msg = "To use the embed directive, install micawber first." return [nodes.raw('', '<div class="text-error">{0}</div>'.format(msg), format='html')] url = " ".join(self.arguments) html = micawber.parse_text(url, self.get_providers()) return [nodes.raw('', html, format='html')]
def run(self): _nodes = [] gallery_dir = self.arguments[0].strip() columns = self.options['columns'] if 'columns' in self.options else 4 if columns == 0 or columns > 5: raise self.error('Minimum number of columns is 1 and maximum is 5') webroot = gallery_dir.replace('content/', '/') if not os.access(gallery_dir, os.R_OK): err = ('Gallery directory {} does not exist or is not ' 'readable'.format(gallery_dir)) raise self.error() images = os.listdir(gallery_dir) if len(images) == 0: err = ('Gallery directory {} does not contain any ' 'images'.format(gallery_dir)) raise self.error(err) i = 0 for image in sorted(images): path = os.path.join(webroot, image) uuid = str(uuid4()) if i == 0: _nodes.append(nodes.raw('', START, format='html')) image_html = IMAGE.format(uuid, path, columns) _nodes.append(nodes.raw('', image_html, format='html')) i = i + 1 if i == columns: _nodes.append(nodes.raw('', END, format='html')) i = 0 return _nodes
def run(self): if pygal is None: msg = ( "ERROR: " "To use the Chart directive you need to install " "the pygal module.\n" ) utils.show_msg(msg) return [nodes.raw('', '<div class="text-error">{0}</div>'.format(msg), format='html')] options = {} if 'style' in self.options: style_name = self.options.pop('style') else: style_name = 'DefaultStyle' if '(' in style_name: # Parametric style style = eval('pygal.style.' + style_name) else: style = getattr(pygal.style, style_name) for k, v in self.options.items(): options[k] = literal_eval(v) chart = getattr(pygal, self.arguments[0])(style=style) chart.config(**options) for line in self.content: label, series = literal_eval('({0})'.format(line)) chart.add(label, series) return [nodes.raw('', chart.render().decode('utf8'), format='html')]
def code(role, rawtext, text, lineno, inliner, options={}, content=[]): # In order to properly preserve backslashes i = rawtext.find('`') text = rawtext.split('`')[1] set_classes(options) classes = [] if 'classes' in options: classes += options['classes'] del options['classes'] # If language is not specified, render a simple literal if not 'language' in options: content = nodes.raw('', utils.unescape(text), format='html') node = nodes.literal(rawtext, '', **options) node.append(content) return [node], [] language = options['language'] del options['language'] # Not sure why language is duplicated in classes? if language in classes: classes.remove(language) class_, highlighted = _highlight(utils.unescape(text), language, options, is_block=False) classes += [class_] content = nodes.raw('', highlighted, format='html') node = nodes.literal(rawtext, '', classes=classes, **options) node.append(content) return [node], []
def run(self): """ Required by the Directive interface. Create docutils nodes """ options = { 'url': self.arguments[0], 'title': self.options.get('title', ''), 'description': self.options.get('description', ''), 'classes': self.options.get('class', ''), 'image_url': self.options.get('image_url', ''), 'author': self.options.get('author', ''), 'author_url': self.options.get('author_url', ''), 'author_by': self.options.get('author_by', ''), } if not options['title']: if options['url'].endswith('/'): options['title'] = options['url'][:-1] options['title'] = options['title'].split('/')[-1] options['title'] = options['title'].split('?')[0] if not options['description']: options['description'] = options['title'] return [nodes.raw('', CODE_URL_BASIC.format(**options), format='html')] if options['image_url']: options['image_url'] = CODE_IMAGE.format(**options) if options['author_by']: options['author_by'] = options['author_by'].strip() + ' ' if options['author'] and options['author_url']: options['author'] = CODE_AUTHOR_URL.format(**options) elif options['author']: options['author'] = CODE_AUTHOR.format(**options) if options['description']: options['description'] = CODE_DESCRIPTION.format(**options) options['url'] = CODE_URL.format(**options) return [nodes.raw('', CODE.format(**options), format='html')]
def html_add_content(app, doctree, docname): field_list = doctree.next_node(nodes.field_list) task_id = '' if field_list: for field in field_list.traverse(nodes.field): field_name = field.next_node(nodes.field_name).astext() if field_name == 'task_id': task_id = field.next_node(nodes.field_body).astext() field_list.parent.remove(field_list) builder = app.builder if not hasattr(builder, 'format') or builder.format != 'html': return h = hashlib.md5(str(doctree)).hexdigest() title = '' node = doctree for t in doctree.traverse(nodes.title): title = t.children[0].astext() node = t.parent break section = nodes.section(ids=["checker"], name=["checker"]) section += nodes.title(text=translations[language]['verify_title']) text = u'<div id="results" style="display: none;"></div>' if app.config.mcq_inginious_url and task_id: text += '<input type="submit" value="' + translations[language]['verify'] + '" id="submit" />' section += nodes.raw(format='html', text=text) node += section js = nodes.raw(format='html') js += nodes.Text(u'\n<script type="text/javascript">var language = "' + unicode(language) + '";' u' var upload_url = "' + unicode(app.config.mcq_upload_url) + '";' u' var hash = "' + unicode(h) + '"; var title = "' + unicode(title) + '";' u' var html_title = "' + unicode(app.config.html_title) + '";') if app.config.mcq_inginious_url and task_id: js += nodes.Text(u' var task_id = "' + unicode(task_id) + '"; var inginious_url = "' + unicode(app.config.mcq_inginious_url) + '";') js += nodes.Text(u'</script>'); doctree += js
def run(self): if micawber is None: msg = req_missing(['micawber'], 'use the media directive', optional=True) return [nodes.raw('', '<div class="text-error">{0}</div>'.format(msg), format='html')] providers = micawber.bootstrap_basic() return [nodes.raw('', micawber.parse_text(" ".join(self.arguments), providers), format='html')]
def run(self): self.assert_has_content() user = self.arguments[0] name = self.arguments[1] element = nodes.paragraph() self.state.nested_parse(self.content, self.content_offset, element) return [ nodes.raw(text=""" <div class="gh-repo"> <div class="gh-title"> <a href="%(url)s">%(name)s</a> <span id="ghrepo-%(user)s-%(name)s"></span> <script>jQuery(function($){ $("#ghrepo-%(user)s-%(name)s").GitHubButton(%(json)s); });</script> </div>""" % { 'url': 'https://github.com/%s/%s' % (user, name), 'name': name, 'user': user, 'json': json.dumps(dict(owner=user, repo=name, text='Star', errorText='?')), 'description': '\n'.join(self.content) }, format='html'), element, nodes.raw(text="</div>", format='html') ]
def run(self): latexPrefix = raw('', '{\\centering', format='latex') latexSuffix = raw('', '\\par}\\bigskip', format='latex') text = '\n'.join(self.content) content_node = compound(rawsource=text) self.state.nested_parse(self.content, self.content_offset, content_node) content_node.attributes['classes'].append('caption') return [latexPrefix, content_node, latexSuffix]
def run(self): url = self.arguments[0].strip() scriptHTML = "<script type='text/javascript' src='https://apis.google.com/js/plusone.js'></script>" linkHTML = "<div class='g-post' data-href='{}'></div>".format(url) return [nodes.raw('', scriptHTML, format='html'), nodes.raw('', linkHTML, format='html')]
def latex_add_content(app, doctree, docname): node_begin = nodes.raw(format='latex') node_end = nodes.raw(format='latex') node_begin += nodes.Text('\n\\begin{Form}') node_end += nodes.Text('\n\\end{Form}') doctree.insert(0, node_begin) doctree.append(node_end) for q in doctree.traverse(Question): q.parent.children.insert(0, nodes.raw(format='latex', text='\n\\needspace{6\\baselineskip}\n'))
def run(self): source = self.arguments[0].strip() order = 'random' gallery = [] if 'columns' in self.options: columns = int(self.options['columns']) if 'order' in self.options: order = self.options['order'] if 'alt' in self.options: alt = self.options['alt'] else: alt = None if 'imgwidth' in self.options: imgwidth = int(self.options['imgwidth']) else: imgwidth = None if 'imgheight' in self.options: imgheight = int(self.options['imgheight']) else: imgheight = None gallery_files = get_gallery_files(source, self.mediaconfig) if 'rows' in self.options: rows = int(self.options['rows']) else: rows = int(len(gallery_files) / columns) gallery_files = gallery_files[:(columns * rows)] if order == 'random': shuffle(gallery_files) gallery.append(nodes.raw('', '<div class="row-fluid clearfix gallery link-file gallery-columns-%s gallery-size-bootstrap-medium-x">' % columns, format='html')) # loop over all stacks, loop over nth stack, if n * stack size > lenght then break for stack in range(columns): gallery.append(nodes.raw('', '<div class="gallery-stack">', format='html')) for row in range(rows): i = stack * rows + row if i < len(gallery_files): gallery.append(nodes.raw('', gallery_item(gallery_files[i], alt, imgwidth, imgheight), format='html')) else: break gallery.append(nodes.raw('', '</div>', format='html')) gallery.append(nodes.raw('', '</div>', format='html')) return gallery
def run(self): if micawber is None: msg = ( "To use the media directive you need to install " "the micawber module." ) utils.logger.WARN(msg) return [nodes.raw('', '<div class="text-error">{0}</div>'.format(msg), format='html')] providers = micawber.bootstrap_basic() return [nodes.raw('', micawber.parse_text(" ".join(self.arguments), providers), format='html')]
def run(self): env = self.state.document.settings.env ret = [] if not env.temp_data.get('cheeseshop_script_written'): env.temp_data['cheeseshop_script_written'] = True ret.append(nodes.raw(RELEASE_SCRIPT, RELEASE_SCRIPT, format='html')) dist = self.arguments[0] prefix = self.options.get('prefix') or 'Download' class_ = self.options.get('class') or '' html = RELEASE_INFO % {'dist': dist, 'prefix': prefix, 'class': class_} ret.append(nodes.raw(html, html, format='html')) return ret
def run(self): if 'alt' in self.options and self.ignore_alt: LOGGER.warning("Graphviz: the :alt: option is ignored, it's better to set the title of your graph.") if self.arguments: if self.content: LOGGER.warning("Graphviz: this directive can't have both content and a filename argument. Ignoring content.") f_name = self.arguments[0] # TODO: be smart about where exactly that file is located with open(f_name, 'rb') as inf: data = inf.read().decode('utf-8') else: data = '\n'.join(self.content) node_list = [] try: p = Popen([self.dot_path, '-Tsvg'], stdin=PIPE, stdout=PIPE, stderr=PIPE) svg_data, errors = p.communicate(input=data.encode('utf8')) code = p.wait() if code: # Some error document = self.state.document return [document.reporter.error( 'Error processing graph: {0}'.format(errors), line=self.lineno)] if self.embed_graph: # SVG embedded in the HTML if 'inline' in self.options: svg_data = '<span class="graphviz">{0}</span>'.format(svg_data) else: svg_data = '<p class="graphviz">{0}</p>'.format(svg_data) else: # External SVG file # TODO: there is no reason why this branch needs to be a raw # directive. It could generate regular docutils nodes and # be useful for any writer. makedirs(self.output_folder) f_name = hashlib.md5(svg_data).hexdigest() + '.svg' img_path = self.graph_path + f_name f_path = os.path.join(self.output_folder, f_name) alt = self.options.get('alt', '') with open(f_path, 'wb+') as outf: outf.write(svg_data) self.state.document.settings.record_dependencies.add(f_path) if 'inline' in self.options: svg_data = '<span class="graphviz"><img src="{0}" alt="{1}"></span>'.format(img_path, alt) else: svg_data = '<p class="graphviz"><img src="{0}" alt="{1}"></p>'.format(img_path, alt) node_list.append(nodes.raw('', svg_data, format='html')) if 'caption' in self.options and 'inline' not in self.options: node_list.append( nodes.raw('', '<p class="caption">{0}</p>'.format(self.options['caption']), format='html')) return node_list except OSError: LOGGER.error("Can't execute 'dot'") raise
def process_helloworld_nodes(app, doctree, fromdocname): for hwnode in doctree.traverse(helloworld): output = f'<em>{hwnode.rawsource}</em>' hwnode.replace_self(nodes.raw('', output, format='html'))
def awesome(name, rawtext, text, lineno, inliner, options={}, content=[]): html = '<span class="{text}"></span>'.format(text=text) return [nodes.raw('', html, format='html')], []
def role(typ, rawtext, text, lineno, inliner, options={}, content=[]): return [nodes.raw('', text, format=format)], []
def issues_role(name, rawtext, text, lineno, inliner, options={}, content=[]): """ Use: :issue|bug|feature|support:`ticket_number` When invoked as :issue:, turns into just a "#NN" hyperlink to `releases_issue_uri`. When invoked otherwise, turns into "[Type] <#NN hyperlink>: ". Spaces present in the "ticket number" are used as fields for keywords (major, backported) and/or specs (e.g. '>=1.0'). This data is removed & used when constructing the object. May give a 'ticket number' of ``-`` or ``0`` to generate no hyperlink. """ parts = utils.unescape(text).split() issue_no = parts.pop(0) # Lol @ access back to Sphinx config = inliner.document.settings.env.app.config if issue_no not in ('-', '0'): ref = None if config.releases_issue_uri: # TODO: deal with % vs .format() ref = config.releases_issue_uri % issue_no elif config.releases_github_path: ref = "https://github.com/{}/issues/{}".format( config.releases_github_path, issue_no) # Only generate a reference/link if we were able to make a URI if ref: identifier = nodes.reference(rawtext, '#' + issue_no, refuri=ref, **options) # Otherwise, just make it regular text else: identifier = nodes.raw(rawtext=rawtext, text='#' + issue_no, format='html', **options) else: identifier = None issue_no = None # So it doesn't gum up dupe detection later # Additional 'new-style changelog' stuff if name in ISSUE_TYPES: nodelist = issue_nodelist(name, identifier) spec = None keyword = None # TODO: sanity checks re: e.g. >2 parts, >1 instance of keywords, >1 # instance of specs, etc. for part in parts: maybe_spec = scan_for_spec(part) if maybe_spec: spec = maybe_spec else: if part in ('backported', 'major'): keyword = part else: err = "Gave unknown keyword {!r} for issue no. {}" raise ValueError(err.format(keyword, issue_no)) # Create temporary node w/ data & final nodes to publish node = Issue( number=issue_no, type_=name, nodelist=nodelist, backported=(keyword == 'backported'), major=(keyword == 'major'), spec=spec, ) return [node], [] # Return old style info for 'issue' for older changelog entries else: return [identifier], []
def run(self): return [nodes.raw('', format='latex')]
def run(self): if 'alt' in self.options and self.ignore_alt: LOGGER.warning( "Graphviz: the :alt: option is ignored, it's better to set the title of your graph." ) if self.arguments: if self.content: LOGGER.warning( "Graphviz: this directive can't have both content and a filename argument. Ignoring content." ) f_name = self.arguments[0] # TODO: be smart about where exactly that file is located with open(f_name, 'rb') as inf: data = inf.read().decode('utf-8') else: data = '\n'.join(self.content) node_list = [] try: p = Popen([self.dot_path, '-Tsvg'], stdin=PIPE, stdout=PIPE, stderr=PIPE) svg_data, errors = p.communicate(input=data) code = p.wait() if code: # Some error document = self.state.document return [ document.reporter.error( 'Error processing graph: {0}'.format(errors), line=self.lineno) ] if self.embed_graph: # SVG embedded in the HTML if 'inline' in self.options: svg_data = '<span class="graphviz">{0}</span>'.format( svg_data) else: svg_data = '<p class="graphviz">{0}</p>'.format(svg_data) else: # External SVG file # TODO: there is no reason why this branch needs to be a raw # directive. It could generate regular docutils nodes and # be useful for any writer. makedirs(self.output_folder) f_name = hashlib.md5(svg_data).hexdigest() + '.svg' img_path = self.graph_path + f_name f_path = os.path.join(self.output_folder, f_name) alt = self.options.get('alt', '') with open(f_path, 'wb+') as outf: outf.write(svg_data) self.state.document.settings.record_dependencies.add( f_path) if 'inline' in self.options: svg_data = '<span class="graphviz"><img src="{0}" alt="{1}"></span>'.format( img_path, alt) else: svg_data = '<p class="graphviz"><img src="{0}" alt="{1}"></p>'.format( img_path, alt) node_list.append(nodes.raw('', svg_data, format='html')) if 'caption' in self.options and 'inline' not in self.options: node_list.append( nodes.raw('', '<p class="caption">{0}</p>'.format( self.options['caption']), format='html')) return node_list except OSError: LOGGER.error("Can't execute 'dot'") raise
def run(self): shadow_files_divs = "" extra_attribs = "" argument_list = [] force_no_buttons = False is_lab = False def get_shadow_div(basename, content): return (u'<div class="shadow_file"' 'style="display:none" basename="{}">' '{}</div>').format(basename, escape(content)) if self.arguments: argument_list = self.arguments[0].split(' ') if 'no_button' in argument_list or ( 'class' in self.options and ('ada-nocheck' in self.options['class'] or 'ada-syntax-only' in self.options['class'])): force_no_buttons = True # look for lab=my_lab_name lab_matches = [ LAB_REGEX.match(line) for line in argument_list if LAB_REGEX.match(line) ] if len(lab_matches) == 1: extra_attribs += ' lab="True"' extra_attribs += ' lab_name={}'.format(lab_matches[0].group(1)) is_lab = True elif len(lab_matches) > 1: raise self.error("malformed lab directive") # Make sure code-config exists in the document if not codeconfig_found: print(self.lineno, dir(self)) raise self.error("you need to add a :code-config: role") if is_lab: # look for lab io start block io_start_matches = [ i for i, line in enumerate(self.content) if LAB_IO_START_REGEX.match(line) ] # look for lab io end block io_end_matches = [ i for i, line in enumerate(self.content) if LAB_IO_END_REGEX.match(line) ] # check for correct formation of lab io block if len(io_start_matches) == 1 and len( io_end_matches ) == 1 and io_start_matches[0] < io_end_matches[0]: io_content = self.content[io_start_matches[0] + 1:io_end_matches[0]] # create shadow file from io blocks new_file = "\n".join(io_content) shadow_files_divs += get_shadow_div(LABIO_FILENAME, new_file) # remove io block lines from self.content # The following does not work for some odd reason so we will have to copy the list # del self.content[io_start_matches[0] : (io_end_matches[0] + 1)] chop_contents = self.content[:io_start_matches[ 0]] + self.content[io_end_matches[0] + 1:] else: raise self.error( "malformed lab io block: io_start={} io_end={}".format( io_start_matches, io_end_matches)) else: chop_contents = self.content # chop contents into files try: # chop source files if 'manual_chop' in argument_list: files = c_chop(chop_contents) elif 'c' in argument_list: files = c_chop(chop_contents) else: files = real_gnatchop(chop_contents) except subprocess.CalledProcessError: raise self.error("could not gnatchop example") if config.accumulate_code: # We are accumulating code: store the new code in the # accumulated_files global accumulated_files for f in files: accumulated_files[f[0]] = f[1] try: if config.accumulate_code: editor_files = set([f[0] for f in files]) for k, v in accumulated_files.items(): if k not in editor_files: shadow_files_divs += get_shadow_div(k, v) divs = "\n".join([ u'<div class="file" basename="{}">{}</div>'.format( f[0], escape(f[1])) for f in files ]) nodes_latex = [] # Attemping to detect HTML or Latex output by checking for 'html' in tags if 'html' not in self.state.state_machine.document.settings.env.app.tags.tags: for f in files: # Based on sphinx/directives/code.py container_node = nodes.container( '', literal_block=True, classes=['literal-block-wrapper']) literal = nodes.literal_block('', f[1], format='latex') literal['language'] = self.arguments[0].split(' ')[0] literal['linenos'] = 'linenos' in self.options or \ 'lineno-start' in self.options literal['source'] = f[0] caption = nodes.caption('', f[0]) caption.source = literal.source caption.line = literal.line container_node += caption container_node += literal nodes_latex.append(container_node) except Exception: # If we have an exception here, it's probably a codec error print(files) raise if not force_no_buttons: for x in (config.buttons | set( filter(lambda y: y.endswith('_button'), argument_list))): extra_attribs += ' {}="True"'.format(x) return [ nodes.raw('', template.format(server_url=WIDGETS_SERVER_URL, files_divs=divs, shadow_files_divs=shadow_files_divs, extra_attribs=extra_attribs), format='html') ] + nodes_latex
def render_hardbreak(self, token): self.current_node.append(nodes.raw("", "<br />\n", format="html"))
def run(self): if self.arguments: # Read code from file document = self.state.document if self.content: return [ document.reporter.warning(__( 'wavedrom directive cannot have both content and ' 'a filename argument'), line=self.lineno) ] argument = search_image_for_language(self.arguments[0], self.env) rel_filename, filename = self.env.relfn2path(argument) self.env.note_dependency(rel_filename) try: with open(filename, 'r') as fp: # type: ignore code = fp.read() except (IOError, OSError): return [ document.reporter.warning(__( 'External wavedrom json file %r not found or reading ' 'it failed') % filename, line=self.lineno) ] else: # Read code from given content code = "\n".join(self.content) if not code.strip(): return [ self.state_machine.reporter.warning( __('Ignoring "wavedrom" directive without content.'), line=self.lineno) ] # For html output with inline JS enabled, just return plain HTML if (self.env.app.builder.name in ('html', 'dirhtml', 'singlehtml') and self.config.wavedrom_html_jsinline): text = WAVEDROM_HTML.format(content=code) content = nodes.raw(text=text, format='html') return [content] # Store code in a special docutils node and pick up at rendering node = wavedromnode() node['code'] = code wd_node = node # point to the actual wavedrom node # A caption option turns this image into a Figure caption = self.options.get('caption') if caption: node = figure_wrapper(self, wd_node, caption) self.add_name(node) # Run image directive processing for the options, supply dummy argument, otherwise will fail. # We don't actually replace this node by the image_node and will also not make it a child, # because intermediate steps, like converters, depend on the file being in sources. We don't # want to generate any files in the user sources. Store the image_node private to this node # and not in the docutils tree and use it later. Revisit this when the situation changes. self.arguments = ["dummy"] (wd_node['image_node'], ) = Image.run(self) return [node]
def translate(self): visitor = PDFTranslator(self.document, self.builder) self.document.walkabout(visitor) lang = self.config.language or 'en' langmod = get_language_available(lang)[2] self.docutils_languages = {lang: langmod} # Generate Contents topic manually if self.use_toc: contents = nodes.topic(classes=['contents']) contents += nodes.title('') contents[0] += nodes.Text(langmod.labels['contents']) contents['ids'] = ['Contents'] pending = nodes.topic() contents.append(pending) pending.details = {} self.document.insert( 0, nodes.raw(text='SetPageCounter 1 arabic', format='pdf')) self.document.insert( 0, nodes.raw(text='OddPageBreak %s' % self.page_template, format='pdf')) self.document.insert(0, contents) self.document.insert( 0, nodes.raw(text='SetPageCounter 1 lowerroman', format='pdf')) contTrans = PDFContents(self.document) contTrans.toc_depth = self.toc_depth contTrans.startnode = pending contTrans.apply() if self.use_coverpage: # Generate cover page # FIXME: duplicate from createpdf, refactor! # Find cover template, save it in cover_file def find_cover(name): cover_path = [ self.srcdir, os.path.expanduser('~/.rst2pdf'), os.path.join(self.PATH, 'templates') ] # Add the Sphinx template paths def add_template_path(path): return os.path.join(self.srcdir, path) cover_path.extend( list(map(add_template_path, self.config.templates_path))) cover_file = None for d in cover_path: if os.path.exists(os.path.join(d, name)): cover_file = os.path.join(d, name) break return cover_file cover_file = find_cover(self.config.pdf_cover_template) if cover_file is None: log.error("Can't find cover template %s, using default" % self.custom_cover) cover_file = find_cover('sphinxcover.tmpl') # This is what's used in the python docs because # Latex does a manual linebreak. This sucks. authors = self.document.settings.author.split('\\') # Feed data to the template, get restructured text. cover_text = createpdf.renderTemplate( tname=cover_file, title=self.document.settings.title or visitor.elements['title'], subtitle='%s %s' % (_('version'), self.config.version), authors=authors, date=ustrftime(self.config.today_fmt or _('%B %d, %Y'))) cover_tree = docutils.core.publish_doctree(cover_text) self.document.insert(0, cover_tree) sio = StringIO() if self.invariant: createpdf.patch_PDFDate() createpdf.patch_digester() createpdf.RstToPdf( sphinx=True, stylesheets=self.stylesheets, language=self.__language, breaklevel=self.breaklevel, breakside=self.breakside, fit_mode=self.fitmode, font_path=self.fontpath, inline_footnotes=self.inline_footnotes, highlightlang=self.highlightlang, splittables=self.splittables, style_path=self.style_path, basedir=self.srcdir, def_dpi=self.default_dpi, real_footnotes=self.real_footnotes, numbered_links=self.use_numbered_links, background_fit_mode=self.fit_background_mode, baseurl=self.baseurl, section_header_depth=self.section_header_depth).createPdf( doctree=self.document, output=sio, compressed=self.compressed) self.output = sio.getvalue()
def _style_role(class_, content, text): content = '<span class="%s">%s</span>' % (class_, text) return [nodes.raw('', content, format='html')], []
def run(self): self.assert_has_content() content = '<br/>'.join(self.content) args = {'noclasses': False} content = '<span class="centered">%s</span>' % content return [nodes.raw('', content, format='html')]
def render_html_inline(self, token): self.current_node.append(nodes.raw("", token.content, format="html"))
def _raw_html_block(self, data): html = self._render_html(source=data) return nodes.raw('', html['body'], format='html')
def update_thebe_context(app, doctree, docname): """Add thebe config nodes to this doctree.""" config_thebe = app.config["thebe_config"] if not config_thebe: return # Thebe configuration if config_thebe is True: config_thebe = {} if not isinstance(config_thebe, dict): raise ValueError( "thebe configuration must be `True` or a dictionary for configuration." ) codemirror_theme = config_thebe.get("codemirror-theme", "abcdef") # Thebe configuration # Choose the kernel we'll use meta = app.env.metadata.get(docname, {}) kernel_name = meta.get("thebe-kernel") if kernel_name is None: if meta.get("kernelspec"): kernel_name = json.loads(meta["kernelspec"]).get("name") else: kernel_name = "python3" # Codemirror syntax cm_language = kernel_name if "python" in cm_language: cm_language = "python" elif cm_language == "ir": cm_language = "r" # Create the URL for the kernel request repo_url = config_thebe.get( "repository_url", "https://github.com/binder-examples/jupyter-stacks-datascience", ) branch = config_thebe.get("repository_branch", "master") path_to_docs = config_thebe.get("path_to_docs", ".").strip("/") + "/" org, repo = _split_repo_url(repo_url) # Update the doctree with some nodes for the thebe configuration thebe_html_config = f""" <script type="text/x-thebe-config"> {{ requestKernel: true, binderOptions: {{ repo: "{org}/{repo}", ref: "{branch}", }}, codeMirrorConfig: {{ theme: "{codemirror_theme}", mode: "{cm_language}" }}, kernelOptions: {{ kernelName: "{kernel_name}", path: "{path_to_docs}{str(Path(docname).parent)}" }}, predefinedOutput: true }} </script> """ doctree.append(nodes.raw(text=thebe_html_config, format="html")) doctree.append( nodes.raw(text=f"<script>kernelName = '{kernel_name}'</script>", format="html") )
def run(self): """Run media directive.""" html = _gen_media_embed(" ".join(self.arguments)) return [nodes.raw('', html, format='html')]
def run(self): document = self.state.document if not document.settings.file_insertion_enabled: return [ document.reporter.warning('File insertion disabled', line=self.lineno) ] if 'pyobject' in self.options and 'lines' in self.options: return [ document.reporter.warning( 'Cannot use both "pyobject" and "lines" options', line=self.lineno) ] rel_filename = self.arguments[0] filename = conf.sourcecode_path + rel_filename file_found = False code_nodes = [] # If the codeinclude is given the full path to a specific file load that file rather than attempting to use multiple languages if os.path.isfile(filename): # Parse the code language from the relative filename path_components = rel_filename.split('/') lang = path_components[0] if len( path_components) > 0 and os.path.isdir( path_components[0]) else 'guess' code_nodes.append(self.create_node(filename, rel_filename, lang)) file_found = True else: # Search for the code in multiple different languages # Remove the extension from the file, if it exists rel_path = os.path.splitext(rel_filename)[0] html_strs = [] tag_str = '' if 'tag' in self.options: tag_str = '_' + self.options.get('tag').replace( " ", "-").replace(",", "_") # Use the name of the code file and the tag name (if it exists) to create a unique ID # The ID must be unique per module page (even if there are other codeincludes # on the same module) so that the jQuery call to tabs() will work properly tab_id = '%s%s_code' % (os.path.basename(rel_path), tag_str) tab_header = '<div id="%s"><ul>' % tab_id # Load the code_lang object from conf.py and maintain the order so that the preferred languages and extensions come first code_lang = json.loads(conf.code_lang, object_pairs_hook=collections.OrderedDict) # Loop through each language and associated extension (in order) for lang in code_lang: # If a specific language was provided as a parameter, set lang to the language provided before looping through extensions if 'lang' in self.options: lang = self.options['lang'] if 'lang' in code_lang[lang]: code_color = code_lang[lang]['lang'] else: print_err( 'Failed to find language name in configuration file ("lang" option)' ) return [ document.reporter.warning( 'Missing "lang" option in code_lang configuration', line=self.lineno) ] if 'ext' not in code_lang[lang]: print_err( 'Failed to find language extentions in configuration file ("ext" option)' ) return [ document.reporter.warning( 'Missing "ext" option in code_lang configuration', line=self.lineno) ] for ext in code_lang[lang]['ext']: # Craft the filename given the code_dir, code_lang, rel_path (with any existing extension stripped), and a file extension filename = '%s%s/%s.%s' % (conf.sourcecode_path, lang, rel_path, ext) if os.path.isfile(filename): # Append a list element with a link which will allow switching between the tabs block_id = '_'.join([tab_id, lang.replace('+', 'p')]) tab_label = lang if 'label' in code_lang[lang]: tab_label = code_lang[lang]['label'] tab_header += '<li><a href="#%s">%s</a></li>' % ( block_id, tab_label.title()) if len(html_strs) == 0: html_strs.append('<div id="%s">' % block_id) else: html_strs[-1] += '<div id="%s">' % block_id html_strs.append('</div>') new_node = self.create_node(filename, rel_filename, code_color) # If the new_node returned is a list, an error occurred in create_node # Return the list containing the error info if type(new_node) is list: return new_node code_nodes.append(new_node) file_found = True # Stop after finding one code file if tabbed code is not enabled or if we are only searching for a single language if not conf.tabbed_codeinc or 'lang' in self.options: break # If a file is found and tabbed code is not enabled or if the code language was specified by a parameter to the directive, break out of the loop if (file_found and not conf.tabbed_codeinc) or 'lang' in self.options: break # Print an error message if no file is found for any language if not file_found: print_err('File %r not found for any language' % filename) return [ document.reporter.warning( 'File %r not found for any language' % filename, line=self.lineno) ] # Append the rest of the HTML for the header of the tabbed container and the JavaScript necessary to create the tabs if len(html_strs) > 0: html_strs[0] = tab_header + '</ul>' + html_strs[0] # Link to additional jQuery UI libraries, so we don't load it on pages where its not needed lib_path = os.path.relpath(conf.odsa_path, conf.ebook_path) + '/lib' html_strs[ -1] += '</div><script>$(function() {$( "#%s" ).tabs();});</script>' % ( tab_id) # If only one code block exists, print the code normally if len(code_nodes) == 1: return code_nodes # If multiple code blocks exist, wrap each one in the HTML nodes that will form the tabbed container node_list = [] node_num = 0 for html_str in html_strs: node_list.append(nodes.raw('', html_str, format='html')) if node_num < len(code_nodes): node_list.append(code_nodes[node_num]) node_num += 1 return node_list
'Problems with "%s" directive URL "%s":\n%s.' % (self.name, self.options['url'], error)) raw_file = io.StringInput( source=raw_text, source_path=source, encoding=encoding, error_handler=(self.state.document.settings.\ input_encoding_error_handler)) try: text = raw_file.read() except UnicodeError, error: raise self.severe('Problem with "%s" directive:\n%s: %s' % (self.name, error.__class__.__name__, error)) attributes['source'] = source else: # This will always fail because there is no content. self.assert_has_content() raw_node = nodes.raw('', text, **attributes) return [raw_node] class Replace(Directive): has_content = True def run(self): if not isinstance(self.state, states.SubstitutionDef): raise self.error( 'Invalid context: the "%s" directive can only be used within ' 'a substitution definition.' % self.name) self.assert_has_content() text = '\n'.join(self.content) element = nodes.Element(text)
def run(self): color = self.arguments[0] html = COLOR_DETAIL.render(color=getattr(named, color).to_css(), text=color) node = nodes.raw("", html, format="html") return [node]
def math_role(role, rawtext, text, lineno, inliner, options={}, content=[]): latex = utils.unescape(text, restore_backslashes=True) url, depth = render_math(inliner.document.settings.rstblog_context, latex) return [nodes.raw('', u'<span class="math">%s</span>' % make_imgtag(url, depth, latex), format='html')], []
def make_param_link(name, rawtext, text, lineno, inliner, options={}, content=[]): # name: The role name, here it will always be 'iconlink' # rawtext: The full parsed role in the document, including the role name and quotes # text: Just the content inside the role's quotes # Break the text string apart according to the pipe character (there should always be 2 pips) try: type, linktext, ref = text.split('|') except ValueError: print('\033[93mIconLink error when parsing: ', rawtext, '\033[0m') return [], [] if type != '': if type == 'ext': # or glossary, or video, or ... node = nodes.reference(rawtext, linktext + ' ', refuri=ref, **options) # node.attributes.__setitem__('icon', 'external') # should pass through to HTML5.py, but not working node.attributes.__setitem__('target', '_blank') # passes through to output node2 = nodes.emphasis('', '') node2.attributes.__setitem__('class', 'fas fa-small fa-external-link-alt') node.append(node2) elif type == 'gloss': # Example in test_case_building.rst # Would be nice if this could use the shortened section URL instead of doc root included node1 = nodes.raw(rawtext, linktext + ' ', format="html") node1.attributes.__setitem__('classes', ['glossdef']) node2 = nodes.reference('', '', refuri=ref, **options) node3 = nodes.emphasis('', '') node3.attributes.__setitem__('class', 'fa fa-tiny fa-question-circle') node2.append(node3) return [node1, node2], [] elif type == 'video': # <a href="glossary.html#glossary-test-case"><i class="fa fa-tiny fa-question-circle"></i></a>` # Example in test_case_execution.rst # Only a link on the icon, would also be nice to use the shortened section URL node = nodes.reference(rawtext, linktext + ' ', refuri=ref, internal=True, **options) node.attributes.__setitem__( 'style', 'font-style: italic; font-weight: bold;') node2 = nodes.emphasis('', '') node2.attributes.__setitem__('class', 'fa fa-tiny fa-play-circle') node.append(node2) elif type == 'pivotal': # example in release_notes_31.rst # Not an icon, but a small image to be used inline base_uri = 'https://www.pivotaltracker.com/n/projects/1533621/stories/' node = nodes.reference(rawtext, ' ', refuri=base_uri + ref, **options) node.attributes.__setitem__('target', '_blank2') # This should make it relative to the _build/ directory node2 = nodes.image(uri='/pictures/pt_logo_small.png', alt=linktext) node2.attributes.__setitem__( 'classes', ['pivotal-icon-width']) # in custom.css node.append(node2) else: print("\033[93mError: no type found for :iconlink: {}\033[0m", type) else: node = nodes.reference(rawtext, linktext, refuri=ref, **options) # Returns A list of nodes to insert into the document tree, and a list of system messages return [node], []
def run(self): env = self.state.document.settings.env app = env.app # filename *or* python code content, but not both if self.arguments and self.content: raise SphinxError( "bokeh-plot:: directive can't have both args and content") # process inline examples here if self.content: app.debug("[bokeh-plot] handling inline example in %r", env.docname) source = '\n'.join(self.content) # need docname not to look like a path docname = env.docname.replace("/", "-") serialno = env.new_serialno(env.docname) js_name = "bokeh-plot-%s-inline-%d.js" % (docname, serialno) # the code runner just needs a real path to cd to, this will do path = join(env.bokeh_plot_auxdir, js_name) (script, js, js_path, source) = _process_script(source, path, env.bokeh_plot_auxdir, js_name) env.bokeh_plot_files[js_name] = (script, js, js_path, source) # process example files here else: example_path = self.arguments[0][:-3] # remove the ".py" # if it's an "internal" example, the python parser has already handled it if example_path in env.bokeh_plot_files: app.debug("[bokeh-plot] handling internal example in %r: %s", env.docname, self.arguments[0]) (script, js, js_path, source) = env.bokeh_plot_files[example_path] # handle examples external to the docs source, e.g. gallery examples else: app.debug("[bokeh-plot] handling external example in %r: %s", env.docname, self.arguments[0]) source = open(self.arguments[0]).read() source = decode_utf8(source) docname = env.docname.replace("/", "-") serialno = env.new_serialno(env.docname) js_name = "bokeh-plot-%s-external-%d.js" % (docname, serialno) (script, js, js_path, source) = _process_script(source, self.arguments[0], env.bokeh_plot_auxdir, js_name) env.bokeh_plot_files[js_name] = (script, js, js_path, source) # use the source file name to construct a friendly target_id target_id = "%s.%s" % (env.docname, basename(js_path)) target = nodes.target('', '', ids=[target_id]) result = [target] linenos = self.options.get('linenos', False) code = nodes.literal_block(source, source, language="python", linenos=linenos, classes=[]) set_source_info(self, code) source_position = self.options.get('source-position', 'below') if source_position == "above": result += [code] result += [nodes.raw('', script, format="html")] if source_position == "below": result += [code] return result
def apply(self, **kwargs): for node in reversed(list(self.document.traverse(nodes.Element))): match = re.match(r'^ *{%\s*(\w+)\s*"([^"]+)"\s*%} *$', node.rawsource) if match: panel_type, title = match.groups() try: visibile, icon = self.panel_defaults[panel_type] except KeyError: raise ValueError(f'Unrecognised panel type {panel_type}', self.panel_defaults.keys()) # Find the body of the panel inner_node = node current_nodes = [] while True: inner_node = inner_node.next_node(descend=False, siblings=True, ascend=False) if inner_node is None: raise ValueError( f'Failed to find end block for {node.rawsource} in {node.source}' ) match = re.match(r'^ *{%\s*(\w+)\s*"([^"]+)"\s*%} *$', node.rawsource) # Check if we're at the end of the panel block if re.match(r'^\s*{%\s*end' + panel_type + r'\s*%}\s*$', inner_node.rawsource): inner_node.parent.remove(inner_node) break current_nodes.append(inner_node) # Create a div panel_body = nodes.container() panel_body.attributes['classes'].append('panel-body') for inner_node in current_nodes: inner_node.parent.remove(inner_node) panel_body.append(inner_node) # Create the title text header_text = nodes.paragraph( ids=[title.replace(' ', '-').lower()]) header_text.append( nodes.raw('', f'<i class="fa fa-{icon}"></i> ', format='html')) header_text.append(nodes.Text(title)) # Create the title bar header = nodes.container() header.attributes['classes'].append('panel-header') if visibile: header.attributes['classes'].append('open') header.append(header_text) # Move the inner nodes to the new container node and replace the parent new_node = nodes.container() new_node.attributes['classes'].append('panel') new_node.attributes['classes'].append('panel-' + panel_type) new_node.append(panel_body) new_node.insert(0, header) node.parent.replace(node, new_node)
def run(self): super(Codelens, self).run() addQuestionToDB(self) self.JS_VARNAME = "" self.JS_VARVAL = "" def raw_dict(input_code, output_trace): ret = dict(code=input_code, trace=output_trace) return ret def js_var_finalizer(input_code, output_trace): global JS_VARNAME ret = dict(code=input_code, trace=output_trace) json_output = json.dumps(ret, indent=None) return "var %s = %s;" % (self.JS_VARNAME, json_output) if self.content: source = "\n".join(self.content) else: source = '\n' CUMULATIVE_MODE = False self.JS_VARNAME = self.options['divid'] + '_trace' env = self.state.document.settings.env self.options['divclass'] = env.config.codelens_div_class if 'showoutput' not in self.options: self.options['embedded'] = 'true' # to set embeddedmode to true else: self.options['embedded'] = 'false' if 'python' not in self.options: if six.PY2: self.options['python'] = 'py2' else: self.options['python'] = 'py3' if 'question' in self.options: curTrace = exec_script_str_local(source, None, CUMULATIVE_MODE, None, raw_dict) self.inject_questions(curTrace) json_output = json.dumps(curTrace, indent=None) self.options['tracedata'] = "var %s = %s;" % (self.JS_VARNAME, json_output) else: self.options['tracedata'] = exec_script_str_local( source, None, CUMULATIVE_MODE, None, js_var_finalizer) res = VIS if 'caption' not in self.options: self.options['caption'] = '' if 'question' in self.options: res += QUESTION if 'tracedata' in self.options: res += DATA else: res += '</div>' addHTMLToDB(self.options['divid'], self.options['basecourse'], res % self.options) raw_node = nodes.raw(self.block_text, res % self.options, format='html') raw_node.source, raw_node.line = self.state_machine.get_source_and_line( self.lineno) return [raw_node]
def br_role(role, rawtext, text, lineno, inliner, options={}, content=[]): return [nodes.raw('', text + '<br/>', format='html')], []
def awesome_link(name, rawtext, text, lineno, inliner, options={}, content=[]): cls, href, _ = re.split(" <|>", text) html = f'<a href="{href}" target="_blank"><span class="{cls}"></span></a>' return [nodes.raw('', html, format='html')], []
def backmatter(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): return [nodes.raw('', '\\backmatter\n\\setcounter{secnumdepth}{-1}\n', format='latex')]
def assemble_doctree(self, docname, title, author, appendices): # FIXME: use the new inline_all_trees from Sphinx. # check how the LaTeX builder does it. self.docnames = set([docname]) self.info(darkgreen(docname) + " ", nonl=1) def process_tree(docname, tree): tree = tree.deepcopy() for toctreenode in tree.traverse(addnodes.toctree): newnodes = [] includefiles = list(map(str, toctreenode['includefiles'])) for includefile in includefiles: try: self.info(darkgreen(includefile) + " ", nonl=1) subtree = process_tree( includefile, self.env.get_doctree(includefile)) self.docnames.add(includefile) except Exception: self.warn('%s: toctree contains ref to nonexisting file %r'\ % (docname, includefile)) else: sof = addnodes.start_of_file(docname=includefile) sof.children = subtree.children newnodes.append(sof) toctreenode.parent.replace(toctreenode, newnodes) return tree tree = self.env.get_doctree(docname) tree = process_tree(docname, tree) self.docutils_languages = {} if self.config.language: self.docutils_languages[self.config.language] = \ get_language_available(self.config.language)[2] if self.opts.get('pdf_use_index', self.config.pdf_use_index): # Add index at the end of the document # This is a hack. create_index creates an index from # ALL the documents data, not just this one. # So, we preserve a copy, use just what we need, then # restore it. #from pudb import set_trace; set_trace() t = copy(self.env.indexentries) try: self.env.indexentries = { docname: self.env.indexentries[docname + '-gen'] } except KeyError: self.env.indexentries = {} for dname in self.docnames: self.env.indexentries[dname] = t.get(dname, []) genindex = self.env.create_index(self) self.env.indexentries = t # EOH (End Of Hack) if genindex: # No point in creating empty indexes index_nodes = genindex_nodes(genindex) tree.append( nodes.raw(text='OddPageBreak twoColumn', format='pdf')) tree.append(index_nodes) # This is stolen from the HTML builder's prepare_writing function self.domain_indices = [] # html_domain_indices can be False/True or a list of index names indices_config = self.config.pdf_domain_indices if indices_config and hasattr(self.env, 'domains'): for domain in self.env.domains.values(): for indexcls in domain.indices: indexname = '%s-%s' % (domain.name, indexcls.name) if isinstance(indices_config, list): if indexname not in indices_config: continue # deprecated config value if indexname == 'py-modindex' and \ not self.config.pdf_use_modindex: continue content, collapse = indexcls(domain).generate() if content: self.domain_indices.append( (indexname, indexcls, content, collapse)) # self.domain_indices contains a list of indices to generate, like # this: # [('py-modindex', # <class 'sphinx.domains.python.PythonModuleIndex'>, # [(u'p', [[u'parrot', 0, 'test', u'module-parrot', 'Unix, Windows', # '', 'Analyze and reanimate dead parrots.']])], True)] # Now this in the HTML builder is passed onto write_domain_indices. # We handle it right here for indexname, indexcls, content, collapse in self.domain_indices: indexcontext = dict( indextitle=indexcls.localname, content=content, collapse_index=collapse, ) # In HTML this is handled with a Jinja template, domainindex.html # We have to generate docutils stuff right here in the same way. self.info(' ' + indexname, nonl=1) print() output = ['DUMMY', '=====', '', '.. _modindex:\n\n'] t = indexcls.localname t += '\n' + '=' * len(t) + '\n' output.append(t) for letter, entries in content: output.append('.. cssclass:: heading4\n\n%s\n\n' % letter) for (name, grouptype, page, anchor, extra, qualifier, description) in entries: if qualifier: q = '[%s]' % qualifier else: q = '' if extra: e = '(%s)' % extra else: e = '' output.append('`%s <#%s>`_ %s %s' % (name, anchor, e, q)) output.append(' %s' % description) output.append('') dt = docutils.core.publish_doctree('\n'.join(output))[1:] dt.insert(0, nodes.raw(text='OddPageBreak twoColumn', format='pdf')) tree.extend(dt) if appendices: tree.append( nodes.raw(text='OddPageBreak %s' % self.page_template, format='pdf')) self.info() self.info('adding appendixes...', nonl=1) for docname in appendices: self.info(darkgreen(docname) + " ", nonl=1) appendix = self.env.get_doctree(docname) appendix['docname'] = docname tree.append(appendix) self.info('done') self.info() self.info("resolving references...") #print tree #print '--------------' self.env.resolve_references(tree, docname, self) #print tree for pendingnode in tree.traverse(addnodes.pending_xref): # This needs work, need to keep track of all targets # so I don't replace and create hanging refs, which # crash if pendingnode.get('reftarget',None) == 'genindex'\ and self.config.pdf_use_index: pendingnode.replace_self( nodes.reference(text=pendingnode.astext(), refuri=pendingnode['reftarget'])) # FIXME: probably need to handle dangling links to domain-specific indexes else: # FIXME: This is from the LaTeX builder and I still don't understand it # well, and doesn't seem to work # resolve :ref:s to distant tex files -- we can't add a cross-reference, # but append the document name docname = pendingnode['refdocname'] sectname = pendingnode['refsectname'] newnodes = [nodes.emphasis(sectname, sectname)] for subdir, title in self.titles: if docname.startswith(subdir): newnodes.append(nodes.Text(_(' (in '), _(' (in '))) newnodes.append(nodes.emphasis(title, title)) newnodes.append(nodes.Text(')', ')')) break else: pass pendingnode.replace_self(newnodes) #else: #pass return tree
def run(self): """ Restructured text extension for inserting embedded AVs with show/hide button """ self.options['address'] = self.arguments[0] self.options['type'] = self.arguments[1] url_params = {} url_params['exerciseServer'] = conf.exercise_server url_params['loggingServer'] = conf.logging_server url_params['scoreServer'] = conf.score_server url_params['moduleOrigin'] = conf.module_origin url_params['module'] = self.options['module'] url_params['selfLoggingEnabled'] = 'false' embed = embedlocal(self.arguments[0]) self.options['exer_name'] = embed[0] self.options['av_address'] = embed[1] + '?' + urllib.urlencode( url_params).replace('&', '&') self.options['width'] = embed[2] self.options['height'] = embed[3] self.options['content'] = '' # TODO: Can replace the embedlocal block with this block after KA exercises are set up to dynamically resize #av_path = self.arguments[0] #self.options['exer_name'] = os.path.basename(av_path).partition('.')[0] #self.options['av_address'] = '%s/%s?%s' % (os.path.relpath(conf.av_dir, conf.ebook_path), av_path, urllib.urlencode(url_params).replace('&', '&')) #self.options['width'] = 800 #self.options['height'] = 450 #self.options['content'] = '' # Load translation langDict = loadTable() # Add the JSAV exercise options to the AV address if 'exer_opts' in self.options and self.options['exer_opts'] != '': self.options['av_address'] += '&' + self.options['exer_opts'] if 'required' not in self.options: self.options['required'] = False if 'points' not in self.options: self.options['points'] = 0 if 'threshold' not in self.options: self.options['threshold'] = 1.0 if 'long_name' not in self.options: self.options['long_name'] = self.options['exer_name'] if 'showhide' not in self.options: self.options['showhide'] = 'hide' if self.options['showhide'] == "show": self.options['show_hide_text'] = langDict["hide"] elif self.options['showhide'] == "hide": self.options['show_hide_text'] = langDict["show"] if 'oembed_url' not in self.options: # Exercise does not use oembed self.options['oembed'] = 'false' if self.options['showhide'] != "none": self.options['content'] = BUTTON_HTML % (self.options) else: # Exercise uses oembed self.options['oembed'] = 'true' self.options['av_address'] = self.options['oembed_url'] parts = self.options['oembed_url'].split("//", 1) self.options['oembed_server'] = parts[0] + "//" + parts[1].split( "/", 1)[0] if self.options['showhide'] == "show": self.options['show_hide_text'] = langDict["hide"] self.options['content'] = BUTTON_HTML % (self.options) elif self.options['showhide'] == "hide": self.options['show_hide_text'] = langDict["show"] self.options['content'] = BUTTON_HTML % (self.options) res = CONTAINER_HTML % (self.options) return [nodes.raw('', res, format='html')]
def run(self): return [nodes.raw("", breakpoint + "\n", format="html")]