(* * 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