bib2html.py: Add incollection bibtype
[shutils.git] / bib2html.py
index 28abd58ecbfebd88bfcdc56099a1a33619139f13..7557ccead879e23eb94afeab328bc2420e01a5cc 100755 (executable)
@@ -1,7 +1,7 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 """Creates a webpage with all entries of a .bib file"""
 
-__version__ = "1.0"
+__version__ = "1.1"
 
 __author__ = "Stefan Huber"
 __email__ = "shuber@sthu.org"
@@ -31,22 +31,44 @@ __license__ = "MIT"
 # OTHER DEALINGS IN THE SOFTWARE.
 
 
-import os, sys, getopt
+import os, sys, getopt, re
+import dateutil.parser
 
 
 def format_latex(text):
-    return text.replace('{', '').replace('}', '').replace('\\', '')
+    # Get rid of matching dollar signs
+    text = re.sub(r'\$([^\$]*)\$', r'\1', text)
+
+    # Replace text
+    subst = {
+        '\\"a': 'ä',
+        '\\"o': 'ö',
+        '\\"u': 'u',
+        '\mathcal': '',
+        '{': '',
+        '}': '',
+        '\\': '',
+        '~': ' ',
+        '---': '–',
+        '--': '–',
+    }
+
+    for a, b in subst.items():
+        text = text.replace(a, b)
+
+    return text
 
 def format_field_span(type, value):
     return "<span class=bibentry_" + type + ">" + format_latex(value) + "</span>"
 
 def format_field(bibentry, field, pre='', post=''):
     if field in bibentry.fields:
-        return format_field_span(field, pre + bibentry.fields[field] + post)
+        if bibentry.fields[field] != "":
+            return format_field_span(field, pre + bibentry.fields[field] + post)
     return ""
 
 def format_author(a):
-    return  ' '.join(' '.join(p) for p in (a.first(), a.middle(), a.prelast(), a.last(), a.lineage()) if p)
+    return  ' '.join(' '.join(p) for p in (a.first_names, a.middle_names, a.prelast_names, a.last_names, a.lineage_names) if p)
 
 def format_authors(entry):
     return ", ".join([format_author(a) for a in entry.persons['author']])
@@ -62,8 +84,9 @@ def format_details_article(entry):
             format_field(entry, 'number', pre='(', post=')'))
     line.append(format_field(entry, 'month', post=' ') + \
             format_field(entry, 'year'))
-    line = filter(lambda l: l != "", line)
+    line.append(format_field(entry, 'note'))
 
+    line = filter(lambda l: l != "", line)
     return [where, ", ".join(line)]
 
 def format_details_inproceedings(entry):
@@ -74,6 +97,24 @@ def format_details_inproceedings(entry):
     line.append(format_field(entry, 'address'))
     line.append(format_field(entry, 'month', post=' ') + \
             format_field(entry, 'year'))
+    line.append(format_field(entry, 'isbn', pre='ISBN '))
+    line.append(format_field(entry, 'note'))
+
+    line = filter(lambda l: l != "", line)
+    return [where, ", ".join(line)]
+
+def format_details_incollection(entry):
+    where = format_field(entry, 'booktitle')
+
+    line = []
+    line.append(format_field(entry, 'publisher'))
+    line.append(format_field(entry, 'pages', pre='pp. '))
+    line.append(format_field(entry, 'address'))
+    line.append(format_field(entry, 'month', post=' ') + \
+            format_field(entry, 'year'))
+    line.append(format_field(entry, 'isbn', pre='ISBN '))
+    line.append(format_field(entry, 'note'))
+
     line = filter(lambda l: l != "", line)
     return [where, ", ".join(line)]
 
@@ -82,6 +123,8 @@ def format_details_thesis(entry):
     line.append(format_field(entry, 'school'))
     line.append(format_field(entry, 'month', post=' ') + \
             format_field(entry, 'year'))
+    line.append(format_field(entry, 'note'))
+
     line = filter(lambda l: l != "", line)
     return [", ".join(line)]
 
@@ -91,16 +134,30 @@ def format_details_book(entry):
     line.append(format_field(entry, 'isbn', pre='ISBN '))
     line.append(format_field(entry, 'month', post=' ') + \
             format_field(entry, 'year'))
+    line.append(format_field(entry, 'note'))
+
+    line = filter(lambda l: l != "", line)
+    return [", ".join(line)]
+
+def format_details_patent(entry):
+    line = []
+    line.append(format_field(entry, 'number', pre='Pat. '))
+    line.append(format_field(entry, 'month', post=' ') + \
+            format_field(entry, 'year'))
+    line.append(format_field(entry, 'note'))
+
     line = filter(lambda l: l != "", line)
     return [", ".join(line)]
 
 def format_links(entry):
+    doi = format_field(entry, 'doi', pre='<a href="http://dx.doi.org/', post='">[DOI]</a>')
     webpdf = format_field(entry, 'webpdf', pre='<a href="', post='">[PDF]</a>')
     weblink = format_field(entry, 'weblink', pre='<a href="', post='">[link]</a>')
+    url = format_field(entry, 'url', pre='<a href="', post='">[url]</a>')
     webslides = format_field(entry, 'webslides', pre='<a href="', post='">[slides]</a>')
     weberrata = format_field(entry, 'weberrata', pre='<a href="',
             post='">[errata]</a>')
-    return " ".join([webpdf, weblink, webslides, weberrata])
+    return " ".join([doi, webpdf, weblink, url, webslides, weberrata])
 
 def format_entry(entry):
     lines = []
@@ -111,8 +168,12 @@ def format_entry(entry):
         lines.extend(format_details_article(entry))
     elif entry.type=='inproceedings':
         lines.extend(format_details_inproceedings(entry))
+    elif entry.type=='incollection':
+        lines.extend(format_details_incollection(entry))
     elif entry.type=='book':
         lines.extend(format_details_book(entry))
+    elif entry.type=='patent':
+        lines.extend(format_details_patent(entry))
     elif entry.type in ['mastersthesis', 'phdthesis']:
         lines.extend(format_details_thesis(entry))
     else:
@@ -125,19 +186,38 @@ def format_entry(entry):
     return "<br/>\n".join(lines)
 
 
-def entryCompareDate(p1, p2):
-    k1, e1 = p1
-    k2, e2 = p2
+def entryDateSortKey(p):
+    k, e = p
 
+    if 'date' in e.fields:
+        return e.fields['date']
 
-    def toStr(e):
-        month = { 'jan' : '01', 'feb' : '02', 'mar' : '03', \
-                'apr' : '04', 'may' : '05', 'jun' : '06', \
-                'jul' : '07', 'aug' : '08', 'sep' : '09', \
-                'oct' : '10', 'nov' : '11', 'dec' : '12'}
-        return e.fields['year'] + "-" + month[e.fields['month'].lower()[0:3]]
+    month2num = { 'jan' : '01', 'feb' : '02', 'mar' : '03', \
+            'apr' : '04', 'may' : '05', 'jun' : '06', \
+            'jul' : '07', 'aug' : '08', 'sep' : '09', \
+            'oct' : '10', 'nov' : '11', 'dec' : '12'}
 
-    return cmp(toStr(e1), toStr(e2))
+    if not 'month' in e.fields:
+        return e.fields['year']
+
+    month = e.fields['month'].lower()[0:3]
+    if month in month2num:
+        month = month2num[month]
+    else:
+        month = ""
+
+    return e.fields['year'] + "-" + month
+
+
+def entryGetYear(e):
+    if 'year' in e.fields:
+        return e.fields['year']
+
+    if 'date' in e.fields:
+        dt = dateutil.parser.isoparse(e.fields['date'])
+        return str(dt.year)
+
+    return None
 
 
 def usage():
@@ -186,24 +266,23 @@ if __name__ == "__main__":
     bib_data = parser.parse_file(bibfile)
     entries = bib_data.entries
 
-    years = list(set([ b.fields['year'] for b in entries.values() ]))
+    years = list(set([entryGetYear(e) for e in entries.values()]))
     years.sort(reverse=True)
 
     for year in years:
 
         print("<h2>" + year + "</h2>")
 
-        iteritems = list(entries.iteritems())
-        iteritems.sort(cmp=entryCompareDate, reverse=True)
+        iteritems = list(entries.items())
+        iteritems.sort(key=entryDateSortKey, reverse=True)
         for key, entry in iteritems:
 
-            if entry.fields['year'] != year:
+            if entryGetYear(entry) != year:
                 continue
 
             print("<div class=bibentry>")
-            print("<a class=bibentry_key id=" + key + ">[" + key + "]</a><br/>")
-
-            print(format_entry(entry).encode('utf8'))
+            print("<a class=bibentry_key id={}>[{}]</a><br/><span class=bibentry_type>{}</span><br/>".format(key, key, entry.type))
+            e = format_entry(entry)
+            print(e)
 
             print("</div>\n")
-