changeset 2508:7e008c174cc3 vim73

Updates for :TOhtml. (Ben Fritz)
author Bram Moolenaar <bram@vim.org>
date Sat, 07 Aug 2010 15:47:30 +0200
parents 2070b63605a7
children 6d6378ba18cb
files runtime/autoload/tohtml.vim runtime/plugin/tohtml.vim runtime/syntax/2html.vim
diffstat 3 files changed, 138 insertions(+), 94 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/autoload/tohtml.vim
+++ b/runtime/autoload/tohtml.vim
@@ -1,6 +1,6 @@
 " Vim autoload file for the tohtml plugin.
 " Maintainer: Ben Fritz <fritzophrenic@gmail.com>
-" Last Change: 2010 Aug 02
+" Last Change: 2010 Aug 06
 "
 " Additional contributors:
 "
@@ -49,20 +49,50 @@ func! tohtml#Convert2HTML(line1, line2)
 endfunc
 
 func! tohtml#Diff2HTML(win_list, buf_list)
-  " TODO: add logic for xhtml
-  let style = ['-->']
+  let xml_line = ""
+  let tag_close = '>'
+
+  if s:settings.use_xhtml
+    if s:settings.encoding != ""
+      let xml_line = "<?xml version=\"1.0\" encoding=\"" . s:settings.encoding . "\"?>"
+    else
+      let xml_line = "<?xml version=\"1.0\"?>"
+    endif
+    let tag_close = ' />'
+  endif
+
+  let style = [s:settings.use_xhtml ? "" : '-->']
   let body_line = ''
 
   let html = []
-  call add(html, '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"')
-  call add(html, '  "http://www.w3.org/TR/html4/loose.dtd">')
-  call add(html, '<html>')
+  if s:settings.use_xhtml
+    call add(html, xml_line)
+  endif
+  if s:settings.use_xhtml
+    call add(html, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">")
+    call add(html, '<html xmlns="http://www.w3.org/1999/xhtml">')
+  elseif s:settings.use_css && !s:settings.no_pre
+    call add(html, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">")
+    call add(html, '<html>')
+  else
+    call add(html, '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"')
+    call add(html, '  "http://www.w3.org/TR/html4/loose.dtd">')
+    call add(html, '<html>')
+  endif
   call add(html, '<head>')
+
+  " include encoding as close to the top as possible, but only if not already
+  " contained in XML information (to avoid haggling over content type)
+  if s:settings.encoding != "" && !s:settings.use_xhtml
+    call add(html, "<meta http-equiv=\"content-type\" content=\"text/html; charset=" . s:settings.encoding . '"' . tag_close)
+  endif
+
   call add(html, '<title>diff</title>')
-  call add(html, '<meta name="Generator" content="Vim/'.v:version/100.'.'.v:version%100.'">')
-  call add(html, '<meta name="plugin-version" content="'.g:loaded_2html_plugin.'">')
-  " TODO: copy or move encoding logic from 2html.vim so generated markup can
-  " validate without warnings about encoding
+  call add(html, '<meta name="Generator" content="Vim/'.v:version/100.'.'.v:version%100.'"'.tag_close)
+  call add(html, '<meta name="plugin-version" content="'.g:loaded_2html_plugin.'"'.tag_close)
+  call add(html, '<meta name="settings" content="'.
+	\ join(filter(keys(s:settings),'s:settings[v:val]'),',').
+	\ '"'.tag_close)
 
   call add(html, '</head>')
   let body_line_num = len(html)
@@ -132,7 +162,13 @@ func! tohtml#Diff2HTML(win_list, buf_lis
     " so we can later save the file as valid html
     " TODO: restore using grabbed lines if undolevel is 1?
     normal 2u
-    call add(html, '<td nowrap valign="top"><div>')
+    if s:settings.use_css
+      call add(html, '<td valign="top"><div>')
+    elseif s:settings.use_xhtml
+      call add(html, '<td nowrap="nowrap" valign="top"><div>')
+    else
+      call add(html, '<td nowrap valign="top"><div>')
+    endif
     let html += temp
     call add(html, '</div></td>')
 
@@ -150,10 +186,10 @@ func! tohtml#Diff2HTML(win_list, buf_lis
   call add(html, '</html>')
 
   let i = 1
-  let name = "Diff" . ".html"
+  let name = "Diff" . (s:settings.use_xhtml ? ".xhtml" : ".html")
   " Find an unused file name if current file name is already in use
   while filereadable(name)
-    let name = substitute(name, '\d*\.html$', '', '') . i . ".html"
+    let name = substitute(name, '\d*\.x\?html$', '', '') . i . '.' . fnamemodify(copy(name), ":t:e")
     let i += 1
   endwhile
   exe "topleft new " . name
@@ -173,7 +209,7 @@ func! tohtml#Diff2HTML(win_list, buf_lis
     if s:settings.dynamic_folds
       call append(style_start, [
 	    \  "<script type='text/javascript'>",
-	    \  "  <!--",
+	    \  s:settings.use_xhtml ? '//<![CDATA[' : "  <!--",
 	    \  "  function toggleFold(objID)",
 	    \  "  {",
 	    \  "    for (win_num = 1; win_num <= ".len(a:buf_list)."; win_num++)",
@@ -190,7 +226,7 @@ func! tohtml#Diff2HTML(win_list, buf_lis
 	    \  "      }",
 	    \  "    }",
 	    \  "  }",
-	    \  "  -->",
+	    \  s:settings.use_xhtml ? '//]]>' : "  -->",
 	    \  "</script>"
 	    \ ])
     endif
@@ -201,16 +237,16 @@ func! tohtml#Diff2HTML(win_list, buf_lis
     " horizontally scrollable when the lines are too long. Otherwise, the diff
     " is pretty useless for really long lines.
     if s:settings.use_css
-      call append(style_start, [
-	    \ '<style type="text/css">']+
-	    \  style+[
-	    \ '<!--',
-	    \ 'table { table-layout: fixed; }',
-	    \ 'html, body, table, tbody { width: 100%; margin: 0; padding: 0; }',
-	    \ 'th, td { width: '.printf("%.1f",100.0/len(a:win_list)).'%; }',
-	    \ 'td div { overflow: auto; }',
-	    \ '-->',
-	    \  '</style>'
+      call append(style_start,
+	    \ ['<style type="text/css">']+
+	    \ style+
+	    \ [ s:settings.use_xhtml ? '' : '<!--',
+	    \   'table { table-layout: fixed; }',
+	    \   'html, body, table, tbody { width: 100%; margin: 0; padding: 0; }',
+	    \   'th, td { width: '.printf("%.1f",100.0/len(a:win_list)).'%; }',
+	    \   'td div { overflow: auto; }',
+	    \   s:settings.use_xhtml ? '' : '-->',
+	    \   '</style>'
 	    \ ])
     endif
   endif
@@ -259,9 +295,12 @@ func! tohtml#GetUserSettings()
     call tohtml#GetOption(user_settings,   'whole_filler',  0 )
     call tohtml#GetOption(user_settings,      'use_xhtml',  0 )
     
-    " TODO: encoding? font? These are string options that require more parsing.
+    " override those settings that need it
 
-    " override those settings that need it
+    " hover opening implies dynamic folding
+    if user_settings.hover_unfold
+      let user_settings.dynamic_folds = 1
+    endif
 
     " ignore folding overrides dynamic folding
     if user_settings.ignore_folding && user_settings.dynamic_folds
@@ -269,11 +308,6 @@ func! tohtml#GetUserSettings()
       let user_settings.hover_unfold = 0
     endif
 
-    " hover opening implies dynamic folding
-    if user_settings.hover_unfold
-      let user_settings.dynamic_folds = 1
-    endif
-
     " dynamic folding with no foldcolumn implies hover opens
     if user_settings.dynamic_folds && user_settings.no_foldcolumn
       let user_settings.hover_unfold = 1
@@ -290,6 +324,41 @@ func! tohtml#GetUserSettings()
       let user_settings.no_pre = 1
     endif
 
+    " Figure out proper MIME charset from the 'encoding' option.
+    if exists("g:html_use_encoding")
+      let user_settings.encoding = g:html_use_encoding
+    else
+      let vim_encoding = &encoding
+      if vim_encoding =~ '^8bit\|^2byte'
+	let vim_encoding = substitute(vim_encoding, '^8bit-\|^2byte-', '', '')
+      endif
+      if vim_encoding == 'latin1'
+	let user_settings.encoding = 'iso-8859-1'
+      elseif vim_encoding =~ "^cp12"
+	let user_settings.encoding = substitute(vim_encoding, 'cp', 'windows-', '')
+      elseif vim_encoding == 'sjis' || vim_encoding == 'cp932'
+	let user_settings.encoding = 'Shift_JIS'
+      elseif vim_encoding == 'big5' || vim_encoding == 'cp950'
+	let user_settings.encoding = "Big5"
+      elseif vim_encoding == 'euc-cn'
+	let user_settings.encoding = 'GB_2312-80'
+      elseif vim_encoding == 'euc-tw'
+	let user_settings.encoding = ""
+      elseif vim_encoding =~ '^euc\|^iso\|^koi'
+	let user_settings.encoding = substitute(vim_encoding, '.*', '\U\0', '')
+      elseif vim_encoding == 'cp949'
+	let user_settings.encoding = 'KS_C_5601-1987'
+      elseif vim_encoding == 'cp936'
+	let user_settings.encoding = 'GBK'
+      elseif vim_encoding =~ '^ucs\|^utf'
+	let user_settings.encoding = 'UTF-8'
+      else
+	let user_settings.encoding = ""
+      endif
+    endif
+
+    " TODO: font
+
     return user_settings
   endif
 endfunc
--- a/runtime/plugin/tohtml.vim
+++ b/runtime/plugin/tohtml.vim
@@ -1,24 +1,22 @@
 " Vim plugin for converting a syntax highlighted file to HTML.
 " Maintainer: Ben Fritz <fritzophrenic@gmail.com>
-" Last Change: 2010 Aug 02
+" Last Change: 2010 Aug 07
 "
 " The core of the code is in $VIMRUNTIME/autoload/tohtml.vim and
 " $VIMRUNTIME/syntax/2html.vim
 "
 " TODO:
 "   * Bug: error thrown when nowrapscan is set
-"   * Diff mode with xhtml gives invalid markup
-"   * Diff mode does not determine encoding
 "   * Line number column has one character too few on empty lines
 "     without CSS.
 "   * Add extra meta info (generation time, etc.)
-"   * Fix strict doctype for other options?
+"   * Tidy up so we can use strict doctype more?
 "   * TODO comments for code cleanup scattered throughout
 
 if exists('g:loaded_2html_plugin')
   finish
 endif
-let g:loaded_2html_plugin = 'vim7.3_v3'
+let g:loaded_2html_plugin = 'vim7.3_v4'
 
 " Define the :TOhtml command when:
 " - 'compatible' is not set
--- a/runtime/syntax/2html.vim
+++ b/runtime/syntax/2html.vim
@@ -1,6 +1,6 @@
 " Vim syntax support file
 " Maintainer: Ben Fritz <fritzophrenic@gmail.com>
-" Last Change: 2010 Aug 05
+" Last Change: 2010 Aug 07
 "
 " Additional contributors:
 "
@@ -73,7 +73,7 @@ else
   endfun
 endif
 
-if s:settings.use_css
+if !s:settings.use_css
   " Return opening HTML tag for given highlight id
   function! s:HtmlOpening(id)
     let a = ""
@@ -198,39 +198,6 @@ if s:settings.dynamic_folds
 
 endif
 
-" Figure out proper MIME charset from the 'encoding' option.
-if exists("g:html_use_encoding")
-  let s:html_encoding = g:html_use_encoding
-else
-  let s:vim_encoding = &encoding
-  if s:vim_encoding =~ '^8bit\|^2byte'
-    let s:vim_encoding = substitute(s:vim_encoding, '^8bit-\|^2byte-', '', '')
-  endif
-  if s:vim_encoding == 'latin1'
-    let s:html_encoding = 'iso-8859-1'
-  elseif s:vim_encoding =~ "^cp12"
-    let s:html_encoding = substitute(s:vim_encoding, 'cp', 'windows-', '')
-  elseif s:vim_encoding == 'sjis' || s:vim_encoding == 'cp932'
-    let s:html_encoding = 'Shift_JIS'
-  elseif s:vim_encoding == 'big5' || s:vim_encoding == 'cp950'
-    let s:html_encoding = "Big5"
-  elseif s:vim_encoding == 'euc-cn'
-    let s:html_encoding = 'GB_2312-80'
-  elseif s:vim_encoding == 'euc-tw'
-    let s:html_encoding = ""
-  elseif s:vim_encoding =~ '^euc\|^iso\|^koi'
-    let s:html_encoding = substitute(s:vim_encoding, '.*', '\U\0', '')
-  elseif s:vim_encoding == 'cp949'
-    let s:html_encoding = 'KS_C_5601-1987'
-  elseif s:vim_encoding == 'cp936'
-    let s:html_encoding = 'GBK'
-  elseif s:vim_encoding =~ '^ucs\|^utf'
-    let s:html_encoding = 'UTF-8'
-  else
-    let s:html_encoding = ""
-  endif
-endif
-
 
 " Set some options to make it work faster.
 " Don't report changes for :substitute, there will be many of them.
@@ -295,8 +262,8 @@ set magic
 let s:lines = []
 
 if s:settings.use_xhtml
-  if s:html_encoding != ""
-    call add(s:lines, "<?xml version=\"1.0\" encoding=\"" . s:html_encoding . "\"?>")
+  if s:settings.encoding != ""
+    call add(s:lines, "<?xml version=\"1.0\" encoding=\"" . s:settings.encoding . "\"?>")
   else
     call add(s:lines, "<?xml version=\"1.0\"?>")
   endif
@@ -317,15 +284,18 @@ endif
 " HTML header, with the title and generator ;-). Left free space for the CSS,
 " to be filled at the end.
 call extend(s:lines, [
-      \"<html>",
-      \"<head>",
-      \("<title>".expand("%:p:~")."</title>"),
-      \("<meta name=\"Generator\" content=\"Vim/".v:version/100.".".v:version%100.'"'.s:tag_close),
-      \("<meta name=\"plugin-version\" content=\"".g:loaded_2html_plugin.'"'.s:tag_close),
-      \])
-if s:html_encoding != ""
-  call add(s:lines, "<meta http-equiv=\"content-type\" content=\"text/html; charset=" . s:html_encoding . '"' . s:tag_close)
+      \ "<html>",
+      \ "<head>"])
+" include encoding as close to the top as possible, but only if not already
+" contained in XML information (to avoid haggling over content type)
+if s:settings.encoding != "" && !s:settings.use_xhtml
+  call add(s:lines, "<meta http-equiv=\"content-type\" content=\"text/html; charset=" . s:settings.encoding . '"' . s:tag_close)
 endif
+call extend(s:lines, [
+      \ ("<title>".expand("%:p:~")."</title>"),
+      \ ("<meta name=\"Generator\" content=\"Vim/".v:version/100.".".v:version%100.'"'.s:tag_close),
+      \ ("<meta name=\"plugin-version\" content=\"".g:loaded_2html_plugin.'"'.s:tag_close)
+      \ ])
 call add(s:lines, '<meta name="syntax" content="'.s:current_syntax.'"'.s:tag_close)
 call add(s:lines, '<meta name="settings" content="'.
       \ join(filter(keys(s:settings),'s:settings[v:val]'),',').
@@ -337,7 +307,7 @@ if s:settings.use_css
       " if we are doing hover_unfold, use css 2 with css 1 fallback for IE6
       call extend(s:lines, [
 	    \ "<style type=\"text/css\">",
-	    \ "<!--",
+	    \ s:settings.use_xhtml ? "" : "<!--",
 	    \ ".FoldColumn { text-decoration: none; white-space: pre; }",
 	    \ "",
 	    \ "body * { margin: 0; padding: 0; }", "",
@@ -356,8 +326,12 @@ if s:settings.use_css
 	    \ ".closed-fold:hover > .fulltext { display: inline; }",
 	    \ ".closed-fold:hover > .toggle-filler { display: none; }",
 	    \ ".closed-fold:hover > .Folded { display: none; }",
-	    \ '-->',
-	    \ '<style>',
+	    \ s:settings.use_xhtml ? "" : '-->',
+	    \ '<style>'])
+      " TODO: IE7 doesn't *actually* support XHTML, maybe we should remove this.
+      " But if it's served up as tag soup, maybe the following will work, so
+      " leave it in for now.
+      call extend(s:lines, [
 	    \ "<!--[if lt IE 7]><style type=\"text/css\">",
 	    \ ".open-fold   .Folded      { display: none; }",
 	    \ ".open-fold   .fulltext      { display: inline; }",
@@ -375,7 +349,7 @@ if s:settings.use_css
       " if we aren't doing hover_unfold, use CSS 1 only
       call extend(s:lines, [
 	    \ "<style type=\"text/css\">",
-	    \ "<!--",
+	    \ s:settings.use_xhtml ? "" :"<!--",
 	    \ ".FoldColumn { text-decoration: none; white-space: pre; }",
 	    \ ".open-fold   .Folded      { display: none; }",
 	    \ ".open-fold   .fulltext      { display: inline; }",
@@ -386,7 +360,7 @@ if s:settings.use_css
 	    \ ".closed-fold .Folded      { display: inline; }",
 	    \ ".closed-fold .toggle-open   { display: inline; }",
 	    \ ".closed-fold .toggle-closed { display: none; }",
-	    \ '-->',
+	    \ s:settings.use_xhtml ? "" : '-->',
 	    \ '</style>'
 	    \])
     endif
@@ -394,8 +368,8 @@ if s:settings.use_css
     " if we aren't doing any dynamic folding, no need for any special rules
     call extend(s:lines, [
 	  \ "<style type=\"text/css\">",
-	  \ "<!--",
-	  \ '-->',
+	  \ s:settings.use_xhtml ? "" : "<!--",
+	  \ s:settings.use_xhtml ? "" : '-->',
 	  \ "</style>",
 	  \])
   endif
@@ -406,7 +380,7 @@ if s:settings.dynamic_folds
   call extend(s:lines, [
 	\ "",
 	\ "<script type='text/javascript'>",
-	\ "<!--",
+	\ s:settings.use_xhtml ? '//<![CDATA[' : "<!--",
 	\ "function toggleFold(objID)",
 	\ "{",
 	\ "  var fold;",
@@ -420,7 +394,7 @@ if s:settings.dynamic_folds
 	\ "    fold.className = 'closed-fold';",
 	\ "  }",
 	\ "}",
-	\ '-->',
+	\ s:settings.use_xhtml ? '//]]>' : '-->',
 	\ "</script>"
 	\])
 endif
@@ -965,7 +939,7 @@ endif
 if s:settings.no_pre
   if !s:settings.use_css
     " Close off the font tag that encapsulates the whole <body>
-    call extend(s:lines, ["</font></body>", "</html>"])
+    call extend(s:lines, ["</font>", "</body>", "</html>"])
   else
     call extend(s:lines, ["</body>", "</html>"])
   endif
@@ -1005,7 +979,7 @@ if s:settings.use_css
     execute "normal! ^cwbody\e"
   endif
 else
-  execute '%s:<body>:<body bgcolor="' . s:bgc . '" text="' . s:fgc . '"><font face="'. s:htmlfont .'">'
+  execute '%s:<body>:<body bgcolor="' . s:bgc . '" text="' . s:fgc . '">\r<font face="'. s:htmlfont .'">'
 endif
 
 " Line numbering attributes
@@ -1053,7 +1027,10 @@ while !empty(s:idlist)
     if s:pgb.needs_redraw
       redrawstatus
       let s:pgb.needs_redraw = 0
-      sleep 50m
+      " TODO: sleep here to show the progress bar, but only if total time spent
+      " so far on this step is < 1 second? Too slow for batch runs like the test
+      " suite to sleep all the time. Maybe there's no good reason to sleep at
+      " all.
     endif
   endif
 endwhile