def to_snippet(self, style): if style == '': self.errors = 'No style specified' return None try: style_file = os.path.join(style_folder, style) bib_style = citeproc.CitationStylesStyle(style=style_file, validate=False) except AttributeError: self.errors = 'The style "{style}" is not available'.format( style=style) return None except lxml.etree.XMLSyntaxError: self.errors = 'The style "{style}" could not be processed'.format( style=style) return None bib_source = citeproc.source.BibliographySource() bib_source.add(self) bibliography = citeproc.CitationStylesBibliography( bib_style, bib_source, citeproc.formatter.plain) citation = citeproc.Citation([citeproc.CitationItem('refkey')]) bibliography.register(citation) if len(bibliography.bibliography()) > 0: snippet = str(bibliography.bibliography()[0]) else: snippet = None return snippet
def apply(self): # Get the document biblio database biblio = self.document.settings.biblio # Get the citation keys raw_cit = self.startnode.details['raw_citation'] keys = raw_cit.split(';') def link_format(key): return 'bib-' + key.lower() # Create a citation and register it def mkitem(key): return citeproc.CitationItem(key, prefix='`', suffix=' <#%s>`_' % link_format(key)) cit = citeproc.Citation([mkitem(key) for key in keys]) biblio.register(cit) # Create a new pending for the second transform pending = docutils.nodes.pending(CitationSecondTransform) pending.details['raw_citation'] = raw_cit pending.details['citation'] = cit pending.details['biblio'] = biblio self.document.note_pending(pending) self.startnode.replace_self(pending)
def process_dom(dom, biblio, citation_separator=';', sort_order='alpha', link_format=lambda x: x.lower()): ''' :param xml.dom.Document dom: Source DOM document. :param str citation_separator: Separator delimiting multiple citations in a single <citation/> element. ''' # Search all citations and their keys cit_nodes = [(n.childNodes[0].data.lower().split(citation_separator),n) for n in dom.getElementsByTagNameNS(docbook_ns, 'citation') if len(n.childNodes) == 1 and n.childNodes[0].nodeType == n.TEXT_NODE] # Create the citations cits = [] for (keys,n) in cit_nodes: def mkitem(key): return citeproc.CitationItem(key, prefix='<link linkend="%s">'%(link_format(key)), suffix='</link>') cit = citeproc.Citation([mkitem(key) for key in keys]) biblio.register(cit) cits.append(cit) # Print the citations def warn(cit_item): print('warning: citation reference not found for', cit_item.key) for ((keys,n),cit) in zip(cit_nodes,cits): txt = str(biblio.cite(cit,warn)) cit_dom = xml.dom.minidom.parseString('<para>%s</para>'%txt) # Remove all previous <citation/> children for node in n.childNodes: n.removeChild(node) # Add the new children cit_root = cit_dom.documentElement while cit_root.hasChildNodes(): n.appendChild(cit_root.firstChild) # Fill the existing bibliography node # TODO: add support for per-section bibliographies for bib_node in dom.getElementsByTagNameNS(docbook_ns, 'bibliography'): # Only keep the bibliography title # TODO: specify which nodes to keep for node in bib_node.childNodes: if node.nodeType == node.ELEMENT_NODE: if node.tagName != 'title': bib_node.removeChild(node) # Add the bibliography entries bib_entries = list(zip(biblio.items,biblio.bibliography())) if sort_order == 'alpha': bib_entries.sort(key=lambda x: x[0].key) # TODO add support for raw entries for (itm,bibitem) in bib_entries: itemdom = xml.dom.minidom.parseString('<bibliomixed xml:id="%s">%s</bibliomixed>'%(link_format(itm.key),str(bibitem))) bib_node.appendChild(itemdom.documentElement) # Only process one bibliography element break
def format_bibtex(bibtex_entry, style='harvard1'): try: from citeproc.source.bibtex import BibTeX as cpBibTeX import citeproc as cp except ImportError as e: raise RuntimeError( "For formatted output we need citeproc and all of its dependencies " "(such as lxml) but there is a problem while importing citeproc: %s" % str(e)) key = bibtex_entry.get_key() # need to save it temporarily to use citeproc-py fname = tempfile.mktemp(suffix='.bib') try: with open(fname, 'wt') as f: bibtex = bibtex_entry.rawentry bibtex = bibtex.replace(u'\u2013', '--') + "\n" # TODO: manage to save/use UTF-8 if PY2: bibtex = bibtex.encode('ascii', 'ignore') f.write(bibtex) # We need to avoid cpBibTex spitting out warnings old_filters = warnings.filters[:] # store a copy of filters warnings.simplefilter('ignore', UserWarning) try: bib_source = cpBibTeX(fname) except Exception as e: lgr.error("Failed to process BibTeX file %s: %s" % (fname, e)) return "ERRORED: %s" % str(e) finally: # return warnings back warnings.filters = old_filters bib_style = cp.CitationStylesStyle(style, validate=False) # TODO: specify which tags of formatter we want bibliography = cp.CitationStylesBibliography(bib_style, bib_source, cp.formatter.plain) citation = cp.Citation([cp.CitationItem(key)]) bibliography.register(citation) finally: if not os.environ.get("DUECREDIT_KEEPTEMP"): os.unlink(fname) biblio_out = bibliography.bibliography() assert(len(biblio_out) == 1) biblio_out = ''.join(biblio_out[0]) return biblio_out # if biblio_out else str(bibtex_entry)
def preprocess_cell(self, cell, resources, index): """ Preprocess cell Parameters ---------- cell : NotebookNode cell Notebook cell being processed resources : dictionary Additional resources used in the conversion process. Allows preprocessors to pass variables into the Jinja engine. cell_index : int Index of the cell being processed (see base.py) """ if cell.cell_type == "markdown": replaced = None if "html" in resources["output_extension"]: replaced = cell.source for citation in re.finditer('<cite data-cite=\\"(.*?)\\"></cite>', cell.source): tempcite = citeproc.Citation([citeproc.CitationItem(citation.groups()[0])]) self.bibliography.register(tempcite) replaced = re.sub('<cite data-cite=\\"'+citation.groups()[0]+'\\"></cite>', '<a href="#'+tempcite['cites'][0]["key"]+'">'+str(self.bibliography.cite(tempcite, cite_warn))+'</a>', replaced) if "<div class=\"cite2c-biblio\"></div>" in cell.source: if "html" in resources["output_extension"]: html_bibliography = '<h2 id="bibliography">Bibliography</h2>' for item, key in zip(self.bibliography.bibliography(), self.bibliography.keys): html_bibliography += '<p id="'+key+'">' html_bibliography += str(item) html_bibliography += '</p>\n' replaced = re.sub("<div class=\"cite2c-biblio\"></div>", html_bibliography, cell.source) elif "tex" in resources["output_extension"]: replaced = re.sub("<div class=\"cite2c-biblio\"></div>", r"\\bibliography{"+resources["output_files_dir"]+"/"+resources["unique_key"]+r"} \n ", cell.source) if replaced: cell.source = replaced return cell, resources
def add_publications(generator): """ Populates context with a list of BibTeX publications. Configuration ------------- generator.settings['PUBLICATIONS_SRC']: local path to the BibTeX file to read. Output ------ generator.context['publications']: List of tuples (key, entry, record, external). See Readme.md for more details. """ if "PUBLICATIONS_SRC" not in generator.settings: return if "PUBLICATIONS_STYLE" not in generator.settings: return refs_file = generator.settings["PUBLICATIONS_SRC"] refs_style = generator.settings["PUBLICATIONS_STYLE"] refs_sort = generator.settings.get("PUBLICATIONS_SORT", "date") supress_warning = generator.settings.get( "PUBLICATIONS_SUPRESS_BIBTEX_WARNING", True) with open(refs_file, "r") as fp: bibtex_data = bibtexparser.load(fp) try: entries = sort_entries(bibtex_data.entries, refs_sort) except ValueError as e: logger.error("%s", e) return unknown_bib_field = "Unsupported BibTeX field" with warnings.catch_warnings(record=True) as w_list: citeproc_data = citeproc.source.bibtex.BibTeX(refs_file) for w in w_list: if supress_warning and unknown_bib_field in str(w.message): logger.info("Warning in citeproc-py '%s'", w.message) else: logger.warning("Warning in citeproc-py '%s'", w.message) citeproc_style = citeproc.CitationStylesStyle(refs_style, validate=False) if not citeproc_style.has_bibliography(): logger.warning("Style '%s' does not include a bibliography", refs_style) return bibliography = citeproc.CitationStylesBibliography(citeproc_style, citeproc_data, citeproc.formatter.html) cite = {} for record in entries: key = record["ID"].lower() cite["key"] = citeproc.Citation([citeproc.CitationItem(key)]) bibliography.register(cite["key"]) for key in bibliography.keys: bibliography.cite(cite["key"], cite_warn) bibitems = {} for key, item in zip(bibliography.keys, bibliography.bibliography()): bibitems[key] = str(item) publications = [] for record in entries: key = record["ID"].lower() entry = bibitems[key] external = {} if "eprinttype" in record and "eprint" in record: if record["eprinttype"] == "arxiv": if "eprintclass" in record: external[ "ARXIV"] = "http://arxiv.org/abs/{eprintclass}/{eprint}".format( **record) else: external["ARXIV"] = "http://arxiv.org/abs/{eprint}".format( **record) if "doi" in record and record["doi"] not in entry: external["DOI"] = record["doi"] publications.append((key, entry, record, external)) generator.context["publications"] = publications
def format_bibtex(bibtex_entry, style='harvard1'): try: from citeproc.source.bibtex import BibTeX as cpBibTeX import citeproc as cp except ImportError as e: raise RuntimeError( "For formatted output we need citeproc and all of its dependencies " "(such as lxml) but there is a problem while importing citeproc: %s" % str(e)) decode_exceptions = UnicodeDecodeError try: from citeproc.source.bibtex.bibparse import BibTeXDecodeError decode_exceptions = (decode_exceptions, BibTeXDecodeError) except ImportError: # this version doesn't yet have this exception defined pass key = bibtex_entry.get_key() # need to save it temporarily to use citeproc-py fname = tempfile.mktemp(suffix='.bib') try: with open(fname, 'wb') as f: f.write(condition_bibtex(bibtex_entry.rawentry)) # We need to avoid cpBibTex spitting out warnings old_filters = warnings.filters[:] # store a copy of filters warnings.simplefilter('ignore', UserWarning) try: try: bib_source = cpBibTeX(fname) except decode_exceptions as e: # So .bib must be having UTF-8 characters. With # a recent (not yet released past v0.3.0-68-g9800dad # we should be able to provide encoding argument bib_source = cpBibTeX(fname, encoding='utf-8') except Exception as e: lgr.error("Failed to process BibTeX file %s: %s" % (fname, e)) return "ERRORED: %s" % str(e) finally: # return warnings back warnings.filters = old_filters bib_style = cp.CitationStylesStyle(style, validate=False) # TODO: specify which tags of formatter we want bibliography = cp.CitationStylesBibliography(bib_style, bib_source, cp.formatter.plain) citation = cp.Citation([cp.CitationItem(key)]) bibliography.register(citation) finally: if not os.environ.get("DUECREDIT_KEEPTEMP"): exceptions = (OSError, WindowsError) if on_windows else OSError for i in range(50): try: os.unlink(fname) except exceptions: if i < 49: sleep(0.1) continue else: raise break biblio_out = bibliography.bibliography() assert (len(biblio_out) == 1) biblio_out = ''.join(biblio_out[0]) return biblio_out # if biblio_out else str(bibtex_entry)
def run(self): #print('running the biblio directive', file=sys.stderr) #print('bibliography directive, content=', self.content, file=sys.stderr) # Get biblio database type db_type = 'bibtex' if 'mendeley' in self.options: db_type = 'mendeley' # Get biblio database if len(self.arguments) == 0: db_path = bibgen.default_database(db_type) else: db_path = self.arguments[0] # Make the biblio path relative to the source directory src_path = self.state.document.current_source if os.path.exists(src_path): src_dir = os.path.dirname(src_path) rel_path = os.path.join(src_dir, db_path) if os.path.exists(rel_path): db_path = rel_path # Other options hidden = 'hidden' in self.options style = self.options.get('style', 'harvard1') encoding = self.options.get('encoding', 'utf-8') sort = self.options.get('sort', 'alpha') # Open a biblio database for the document, # possibly replacing a command-line one. biblio = bibgen.open_bibliography(db_type, db_path, encoding, style, 'rst') # Create citations for the content if len(self.content) > 0: for key in self.content: itm = citeproc.CitationItem(key) cit = citeproc.Citation([itm]) biblio.register(cit) # Cite every bibliographic entry if asked elif 'all' in self.options: for key in biblio.source: itm = citeproc.CitationItem(key) cit = citeproc.Citation([itm]) biblio.register(cit) # Only ibliography directives without content are citable else: self.state.document.settings.biblio = biblio pending = docutils.nodes.pending(BibliographyTransform) pending.details['biblio'] = biblio pending.details['hidden'] = hidden pending.details['sort'] = sort self.state.document.note_pending(pending) # The bibliography will be filled after the cite transforms node = docutils.nodes.section(classes=['bibliography'], names=['bibliography'], ids=['bibliography']) title = docutils.nodes.title('', 'Bibliography') node.setup_child(title) node += title node.setup_child(pending) node += pending return [node]