4 # HTML to LaTeX converter
5 # by A. Ito, 16 June, 1997
11 def gif2eps(giffile,epsfile)
12 cmd = "convert #{giffile} #{epsfile}"
17 ###########################################################################
20 if str =~ /<(.+)>/ then
24 @tagname = tags.shift.downcase
28 tn,tv = t.split(/\s*=\s*/,2)
31 @vals[tn.downcase] = tv
33 @vals[t.downcase] = TRUE
64 if file.kind_of?(File) then
73 def read_until(endsym)
77 while @bpos < @buf.size
85 if c == 10 || c == 13 then
104 @buf = Kconv.toeuc(@f.gets)
110 if @buf[@bpos] == TAG_START then
111 return Tag.new(read_until(TAG_END))
112 elsif @buf[@bpos] == AMP_START then
113 return replace_amp(read_until(AMP_END))
116 while i < @buf.size && @buf[i] != TAG_START && @buf[i] != AMP_START
119 r = @buf[@bpos,i-@bpos]
120 if i == @buf.size then
135 if AMP_REPLACE_TABLE.key?(s) then
136 return AMP_REPLACE_TABLE[s]
146 \documentstyle[epsf]{jarticle}
147 \def\hr{\par\hbox to \textwidth{\hrulefill}}
148 \def\pre{\begin{quote}\def\baselinestretch{0.8}\tt\obeylines}
149 \def\endpre{\end{quote}}
151 \@ifundefined{gt}{\let\gt=\dg}{}
158 def initialize(*envs)
162 if tag =~ /^!/ then # comment
167 a = @stack[i].action(tag)
182 @stack[@stack.size-1]
185 @stack.push(top.clone)
191 def initialize(interp)
202 if tok.kind_of?(String) then
203 tok = tok.gsub(/&/,"\\&");
204 tok = tok.gsub(/%/,"\\%");
205 tok = tok.gsub(/#/,"\\#");
206 tok = tok.gsub(/\$/,"\\$");
207 tok = tok.gsub(/_/,"\\verb+_+");
208 tok = tok.gsub(/\^/,"\\verb+^+");
209 tok = tok.gsub(/~/,"\\verb+~+");
212 @table[@table_rows][@table_cols] += tok
214 if !@align.nil? && tok =~ /\n$/ then
215 print tok.chop,"\\\\\n"
222 def set_interp(interp)
226 # tag processing methods
240 src = tag.switch('src')
241 newfile = src.sub(/\.GIF/i,".eps")
243 flush "\\epsfile{file=#{newfile}}\n"
253 unless tag.switch('border').nil? then
256 @table_border = FALSE
263 @table[@table_rows] = []
264 @tablespan[@table_rows] = []
271 @colspan = tag.switch('colspan')
272 if @colspan.nil? then
275 @colspan = @colspan.to_i
277 @tablespan[@table_rows][@table_cols+1] = @colspan
278 @table_cols += @colspan
279 if @table_cols > @table_cols_max then
280 @table_cols_max = @table_cols
287 flush "\\begin{tabular}{*{"
288 flush @table_cols_max+1
289 if @table_border then
290 flush "}{|l}|}\n\\hline\n"
294 for i in 0..@table_rows
296 while j <= @table_cols
297 span = @tablespan[i][j]
300 elsif @table_border then
302 if j+span > @table_cols then
305 flush "\\multicolumn{"+span.to_s+"}{"+form+"}{"
306 flush @table[i][j+span-1]
309 flush "\\multicolumn{"+span.to_s+"}{l}{"
310 flush @table[i][j+span-1]
314 if j <= @table_cols then
319 flush "\\hline\n" if @table_border
321 flush "\\end{tabular}\n"
329 flush "\\begin{center}\n"
338 flush "\\end{center}\n"
344 align = tag.switch('align')
349 align = align.downcase
352 flush "\\begin{flushleft}\n"
353 @endparagraph = "\\end{flushleft}\n"
355 flush "\\begin{center}\n"
356 @endparagraph = "\\end{center}\n"
358 flush "\\begin{flushright}\n"
359 @endparagraph = "\\end{flushright}\n"
366 def endparagraph(tag)
367 unless @align.nil? then
376 'li' => ["\\item ",nil]
380 'li' => ["\\item ",nil]
384 'dt' => ["\\item[",nil],
389 'tr' => [:start_row,nil],
390 'td' => [:start_col,nil],
396 '/p' => [:endparagraph ,"pop",TRUE],
400 'body' => ["\\begin{document}\n",nil,FALSE],
401 '/body' => ["\\end{document}\n",nil,FALSE],
402 'head' => ["",nil,FALSE],
403 '/head' => ["",nil,FALSE],
404 'html' => ["",nil,FALSE],
405 '/html' => ["",nil,FALSE],
406 'title' => [:do_silent,nil,FALSE],
407 '/title' => [:undo_silent,nil,FALSE],
408 '!' => ["",nil,FALSE],
409 'h1' => ["\\section{",nil,TRUE],
410 'h2' => ["\\subsection{",nil,TRUE],
411 'h3' => ["\\subsubsection{",nil,TRUE],
412 'h4' => ["\\paragraph{",nil,TRUE],
413 '/h1' => ["}\n",nil,TRUE],
414 '/h2' => ["}\n",nil,TRUE],
415 '/h3' => ["}\n",nil,TRUE],
416 '/h4' => ["}\n",nil,TRUE],
417 'a' => ["",nil,TRUE],
418 '/a' => ["",nil,TRUE],
419 'center' => [:startcenter,nil,TRUE],
420 '/center' => [:endcenter,nil,TRUE],
421 'ol' => ["\\begin{enumerate}\n",enum_interp,TRUE],
422 '/ol' => ["\\end{enumerate}\n","pop",TRUE],
423 'ul' => ["\\begin{itemize}\n",item_interp,TRUE],
424 '/ul' => ["\\end{itemize}\n","pop",TRUE],
425 'dl' => ["\\begin{description}\n",desc_interp,TRUE],
426 '/dl' => ["\\end{description}\n","pop",TRUE],
427 'pre' => ["\\begin{pre}\n",nil,TRUE],
428 '/pre' => ["\\end{pre}\n",nil,TRUE],
429 'p' => [:paragraph ,para_interp,TRUE],
430 'br' => ["\\par ",nil,TRUE],
431 'img' => [:img_proc,nil,TRUE],
432 'hr' => ["\\hr ",nil,TRUE],
433 'b' => ["{\\bf\\gt ",nil,TRUE],
434 '/b' => ["}",nil,TRUE],
435 'strong' => ["{\\bf\\gt ",nil,TRUE],
436 '/strong' => ["}",nil,TRUE],
437 'dfn' => ["{\\bf\\gt ",nil,TRUE],
438 '/dfn' => ["}",nil,TRUE],
439 'i' => ["{\\it",nil,TRUE],
440 '/i' => ["}",nil,TRUE],
441 'address' => ["{\\it",nil,TRUE],
442 '/address'=> ["}",nil,TRUE],
443 'cite' => ["{\\it",nil,TRUE],
444 '/cite' => ["}",nil,TRUE],
445 'code' => ["{\\tt",nil,TRUE],
446 '/code' => ["}",nil,TRUE],
447 'kbd' => ["{\\tt",nil,TRUE],
448 '/kbd' => ["}",nil,TRUE],
449 'tt' => ["{\\tt",nil,TRUE],
450 '/tt' => ["}",nil,TRUE],
451 'samp' => ["{\\tt",nil,TRUE],
452 '/samp' => ["}",nil,TRUE],
453 'em' => ["{\\em",nil,TRUE],
454 '/em' => ["}",nil,TRUE],
455 'u' => ["$\\underline{\\mbox{",nil,TRUE],
456 '/u' => ["}}$",nil,TRUE],
457 'sub' => ["${}_\mbox{",nil,TRUE],
458 '/sub' => ["}$",nil,TRUE],
459 'sup' => ["${}^\mbox{",nil,TRUE],
460 '/sup' => ["}$",nil,TRUE],
461 'table' => [:starttable, table_interp,TRUE],
462 '/table' => [:endtable, "pop",TRUE],
463 'font' => ["",nil,TRUE],
464 '/font' => ["",nil,TRUE],
470 ################################ MAIN ####################################
474 intp = Environ_stack.new(Environment.new(main_interp))
475 f = TokenStream.new(ARGV[0])
478 if tok.kind_of?(Tag) then
485 act = intp.action(tok.tagname)
487 STDERR.print "tag ",tok.tagname," ignored\n"
489 if act[2] && !$in_document then
490 print "\\begin{document}\n"
494 if act[1].kind_of?(Hash) &&
495 (tok.tagname != "p" || tok.switch('align') != nil) then
497 intp.top.set_interp(act[1])
500 if act[0].kind_of?(String) then
501 intp.top.flush act[0]
502 elsif act[0].kind_of?(Fixnum) then # interned symbol
503 intp.top.send(act[0],tok)
507 if act[1] == "pop" then
516 print "\\end{document}\n"