(*
* bibtex2html - A BibTeX to HTML translator
* Copyright (C) 1997-2000 Jean-Christophe Filliātre and Claude Marché
*
* This software is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU General Public License version 2 for more details
* (enclosed in the file GPL).
*)
(*i $Id: translate.ml,v 1.76 2006-11-02 11:58:41 filliatr Exp $ i*)
(*s Production of the HTML documents from the BibTeX bibliographies. *)
open Printf
(*s Options. *)
let nodoc = ref false
let nokeys = ref false
let file_suffix = ref ".html"
let link_suffix = ref ".html"
let raw_url = ref false
let title = ref ""
let title_spec = ref false
let print_abstract = ref true
let print_keywords = ref true
let print_links = ref true
let print_header = ref true
let print_footer = ref true
let multiple = ref false
let single = ref false
let both = ref false
let user_footer = ref ""
let bib_entries = ref true
let links_in_bib_file = ref true
let input_file = ref ""
let output_file = ref ""
let bibentries_file = ref ""
let title_url = ref false
let use_label_name = ref false
let use_keys = ref false
let linebreak = ref false
let note_fields = ref ([] : string list)
let abstract_name = ref "Abstract"
let doi = ref true
let doi_prefix = ref "http://dx.doi.org/"
type table_kind = Table | DL | NoTable
let table = ref Table
(* internal name, plus optional external name *)
type field_info = string * (string option)
let default_fields =
List.map (fun x -> x, None)
["FTP"; "HTTP"; "URL"; "DVI"; "PS"; "POSTSCRIPT"; "PDF";
"DOCUMENTURL"; "URLPS"; "URLDVI"; "URLPDF"]
let (fields : field_info list ref) = ref default_fields
let add_field s =
let u = String.uppercase s in
Biboutput.add_link_field u;
fields := (u, None) :: (List.remove_assoc u !fields)
let add_named_field s name =
let u = String.uppercase s in
Biboutput.add_link_field u;
if u = "ABSTRACT" then abstract_name := name;
if not !both || u <> "ABSTRACT" then
fields := (u, Some name) :: (List.remove_assoc u !fields)
let add_note_field s =
let u = String.uppercase s in
note_fields := !note_fields @ [u]
(* first pass to get the crossrefs *)
let (cite_tab : (string,string) Hashtbl.t) = Hashtbl.create 17
let cpt = ref 0
let first_pass bl =
let rec pass = function
| [] -> ()
| (None,_,(_,k,_)) :: rem ->
incr cpt;
Hashtbl.add cite_tab k (string_of_int !cpt);
pass rem
| (Some c,_,(_,k,_)) :: rem ->
Hashtbl.add cite_tab k c;
pass rem
in
cpt := 0;
Hashtbl.clear cite_tab;
List.iter (fun (_,items) -> pass items) bl
(* latex2html : to print LaTeX strings in HTML format *)
let latex2html ch s =
Latexmacros.out_channel := ch;
Latexscan.brace_nesting := 0;
Latexscan.main (Lexing.from_string s)
open Latexmacros
let in_summary = ref false
let cite k =
try
let url =
if !in_summary then
sprintf "#%s" k
else
sprintf "%s%s#%s" !output_file !link_suffix k
in
let c = if !use_keys then k else Hashtbl.find cite_tab k in
print_s (sprintf "[" url);
latex2html !out_channel c;
print_s "]"
with
Not_found -> print_s "[?]"
let _ = def "\\cite" [ Raw_arg cite ]
let safe_title e =
try Expand.get_title e with Not_found -> "No title"
(* header and footer of HTML files *)
let own_address = "http://www.lri.fr/~filliatr/bibtex2html/"
let header ch =
let print_arg s =
if String.contains s ' ' then
fprintf ch "\"%s\" " s
else
fprintf ch "%s " s
in
fprintf ch "
\n\n"
let footer ch =
Html.open_balise ch "hr";
Html.open_balise ch "p";
Html.open_balise ch "em";
output_string ch "This file has been generated by\n";
Html.open_href ch own_address;
output_string ch "bibtex2html";
Html.close_href ch;
output_string ch " "; output_string ch Version.version; output_string ch ".";
Html.close_balise ch "em";
Html.close_balise ch "p";
output_string ch "\n";
output_string ch !user_footer
(* links (other than BibTeX entry, when available) *)
let compression_suffixes = [ ".gz"; ".Z"; ".zip" ]
let file_suffixes =
List.flatten
(List.map (fun s -> s :: List.map ((^) s) compression_suffixes)
[ ".dvi"; ".DVI"; ".ps"; ".PS"; ".pdf"; ".PDF";
".rtf"; ".RTF"; ".txt"; ".TXT"; ".html"; ".HTML" ])
let is_http s =
String.length s > 3 & String.lowercase (String.sub s 0 4) = "http"
let is_ftp s =
String.length s > 2 & String.lowercase (String.sub s 0 3) = "ftp"
let is_www s =
String.length s > 3 & String.lowercase (String.sub s 0 4) = "www:"
let is_url s = is_http s || is_ftp s || is_www s
let file_type f =
try
List.find (Filename.check_suffix f) file_suffixes
with Not_found ->
if is_http f then "http" else if is_ftp f then "ftp" else "www:"
let get_url s =
if (String.length s > 3 & String.lowercase (String.sub s 0 3) = "www") then
String.sub s 4 (String.length s - 4)
else
s
let link_name (u, name) url s = match name with
| Some name ->
name
| None ->
if !raw_url then
url
else if !use_label_name then
String.capitalize (String.lowercase u)
else
s
type link = { l_url : string; l_name : string }
let display_links ch links =
let rec display = function
| [] ->
output_string ch " ]\n"
| l :: r ->
Html.open_href ch l.l_url;
output_string ch l.l_name;
Html.close_href ch;
if r <> [] then output_string ch " | \n";
display r
in
if !print_links && links <> [] then begin
output_string ch "[ "; display links
end
exception Caught
let rec map_succeed f = function
| [] ->
[]
| x :: l ->
try let y = f x in y :: map_succeed f l with Caught -> map_succeed f l
let make_links ((t,k,_) as e) =
(* URL's *)
map_succeed
(fun ((f, _) as info) ->
try
let u = Expand.get_uppercase_field e f in
let s = file_type u in
let url = get_url u in
{ l_url = url; l_name = link_name info url s }
with Not_found -> raise Caught)
!fields
type abstract =
| Alink of link
| Atext of string
| No_abstract
let make_abstract ((t,k,_) as e) =
try
let a = Expand.get_uppercase_field e "ABSTRACT" in
if is_url a then begin
(* 1. it is an URL *)
Alink { l_url = get_url a; l_name = !abstract_name }
end else if !print_abstract then begin
(* 2. we have to print it right here *)
Atext a
end else if !both then begin
(* 3. we have to insert a link to the file f-abstracts *)
let url = sprintf "%s_abstracts%s#%s" !output_file !link_suffix k in
Alink { l_url = url; l_name = !abstract_name }
end else
No_abstract
with Not_found ->
No_abstract
let blockquote ch f =
(* JK Html.paragraph ch; output_string ch "\n"; *)
Html.open_balise ch "blockquote";
let font_size = not !multiple && !Html.css = None in
if font_size then Html.open_balise ch "font size=\"-1\"";
output_string ch "\n";
f (); output_string ch "\n";
if font_size then Html.close_balise ch "font";
Html.close_balise ch "blockquote";
output_string ch "\n"
let display_abstract ch a = blockquote ch (fun () -> latex2html ch a)
let display_notes ch e =
List.iter
(fun f ->
try
let a = Expand.get_uppercase_field e f in
display_abstract ch a;
(* JK Html.paragraph ch *)
with Not_found -> ())
!note_fields
let display_keywords ch e =
try
let k = Expand.get_uppercase_field e "KEYWORDS" in
blockquote ch (fun () -> output_string ch "Keywords: "; latex2html ch k)
with Not_found ->
()
let doi_link e =
if !doi then begin
try
let k = Expand.get_uppercase_field e "DOI" in
[{ l_url = !doi_prefix ^ k; l_name = "DOI" }]
with Not_found -> []
end else
[]
(* Printing of one entry *)
let bibtex_entry k =
{ l_url =
sprintf "%s%s#%s" !bibentries_file !link_suffix k;
l_name =
"bib" }
let separate_file (b,((_,k,f) as e)) =
in_summary := false;
let file = k ^ !file_suffix in
let ch = open_out file in
if not !nodoc then begin
let f = if !title_spec then !title else !output_file in
let title = sprintf "%s : %s" f k in
Html.open_document ch (fun () -> output_string ch title)
end;
if !print_header then header ch;
Html.open_balise ch "h2";
latex2html ch b;
Html.close_balise ch "h2";
(* JK Html.paragraph ch; *)
let labs = match make_abstract e with
| Atext a -> display_abstract ch a; []
| Alink l -> [l]
| No_abstract -> []
in
Html.paragraph ch;
display_notes ch e;
if !print_keywords then display_keywords ch e;
display_links ch (labs @ bibtex_entry k :: doi_link e @ make_links e);
(* JK Html.paragraph ch; *)
Html.open_href ch (!output_file ^ !link_suffix);
output_string ch "Back";
Html.close_href ch;
if !print_footer then footer ch;
if not !nodoc then Html.close_document ch;
close_out ch;
in_summary := true
let open_table ch = match !table with
| Table -> Html.open_balise ch "table"
| DL -> Html.open_balise ch "dl"
| NoTable -> ()
let close_table ch = match !table with
| Table -> Html.close_balise ch "table"
| DL -> Html.close_balise ch "dl"
| NoTable -> ()
let open_row ch = match !table with
| Table ->
Html.open_balise ch "tr valign=\"top\""; output_string ch "\n";
Html.open_balise ch "td align=\"right\""; output_string ch "\n"
| DL ->
Html.open_balise ch "dt"; output_string ch "\n"
| NoTable ->
Html.open_balise ch "p"
let new_column ch = match !table with
| Table ->
Html.close_balise ch "td"; output_string ch "\n";
Html.open_balise ch "td"; output_string ch "\n"
| DL ->
Html.close_balise ch "dt"; output_string ch "\n";
Html.open_balise ch "dd"; output_string ch "\n"
| NoTable ->
output_string ch "\n"
let close_row ch = match !table with
| Table ->
Html.close_balise ch "td"; output_string ch "\n";
Html.close_balise ch "tr"; output_string ch "\n"
| DL ->
(* JK Html.paragraph ch; output_string ch "\n"; *)
Html.close_balise ch "dd"; output_string ch "\n"
| NoTable ->
Html.close_balise ch "p"
let one_entry_summary ch biblio (_,b,((_,k,f) as e)) =
if !Options.debug then begin
eprintf "[%s]" k; flush stderr
end;
output_string ch "\n\n";
open_row ch;
(* JK changes *)
if (not !nokeys) or !multiple then output_string ch "[";
Html.open_anchor ch k;
if (not !nokeys) or !multiple then begin
if !multiple then Html.open_href ch (k ^ !link_suffix);
latex2html ch (if !use_keys then k else Hashtbl.find cite_tab k);
if !multiple then Html.close_href ch;
end else
if !table <> NoTable then output_string ch " ";
Html.close_anchor ch;
if (not !nokeys) or !multiple then output_string ch "]";
(* end of JK changes *)
output_string ch "\n";
new_column ch;
latex2html ch b;
if !linebreak then Html.open_balise ch "br /";
output_string ch "\n";
if !multiple then
separate_file (b,e)
else if !single then begin
let ks = Bibtex.KeySet.singleton k in
let ks = Bibfilter.saturate biblio ks in
Biboutput.output_bib ~html:true ch biblio (Some ks);
end else begin
let links = doi_link e @ make_links e in
let links = if !bib_entries then bibtex_entry k :: links else links in
match make_abstract e with
| Atext a ->
display_links ch links; display_abstract ch a; Html.paragraph ch
| Alink l -> display_links ch (links @ [l])
| No_abstract -> display_links ch links
end;
display_notes ch e;
if !print_keywords then display_keywords ch e;
output_string ch "\n";
close_row ch
(* summary file f.html *)
let summary biblio bl =
let (ch,filename) =
if !output_file = "" then
(stdout, "standard output")
else
let filename = !output_file ^ !file_suffix in
(open_out filename, filename)
in
if not !Options.quiet then begin
eprintf "Making HTML document (%s)..." filename; flush stderr
end;
if not !nodoc then
Html.open_document ch (fun () -> output_string ch !title);
if !print_header then header ch;
if !title_spec then Html.h1_title ch !title;
output_string ch "\n";
in_summary := true;
List.iter
(fun (name,el) ->
begin match name with
| None -> ()
| Some s ->
Html.open_balise ch "h2";
latex2html ch s;
Html.close_balise ch "h2";
output_string ch "\n"
end;
open_table ch;
List.iter (one_entry_summary ch biblio) el;
close_table ch)
bl;
in_summary := false;
if !print_footer then footer ch;
if not !nodoc then Html.close_document ch;
close_out ch;
if not !Options.quiet then begin eprintf "ok\n"; flush stderr end
(* HTML file with BibTeX entries f_bib.html *)
let print_list print sep l =
let rec print_rec = function
| [] -> ()
| [x] -> print x
| x::r -> print x; sep(); print_rec r
in
print_rec l
let bib_file bl keys =
let fn = !bibentries_file ^ !file_suffix in
if not !Options.quiet then begin
eprintf "Making HTML list of BibTeX entries (%s)..." fn;
flush stderr
end;
let ch = open_out fn in
if not !nodoc then begin
let t = if !title_spec then !title else !input_file in
Html.open_document ch (fun _ -> output_string ch t)
end;
Html.open_balise ch "h1";
output_string ch !input_file;
Html.close_balise ch "h1";
let output_bib =
if !links_in_bib_file then
let html_file = !output_file ^ !link_suffix in
Biboutput.output_bib ~html:true ~html_file ch
else
Biboutput.output_bib ~html:true ch
in
output_bib bl keys;
if !print_footer then footer ch;
if not !nodoc then Html.close_document ch;
flush ch;
close_out ch;
if not !Options.quiet then begin eprintf "ok\n"; flush stderr end
(* main function *)
let format_list biblio sorted_bl keys =
first_pass sorted_bl;
bibentries_file := !output_file ^ "_bib";
if !both then begin
let old_print_keywords = !print_keywords in
(* short version *)
print_abstract := false;
print_keywords := false;
summary biblio sorted_bl;
(* long version with abstracts and keywords *)
print_abstract := true;
print_keywords := old_print_keywords;
let old_output = !output_file in
output_file := !output_file ^ "_abstracts";
summary biblio sorted_bl;
output_file := old_output
end else
summary biblio sorted_bl;
(* BibTeX entries file *)
if !bib_entries then bib_file biblio keys