summaryrefslogtreecommitdiff
path: root/runtime/syntax/2html.vim
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/syntax/2html.vim')
-rw-r--r--runtime/syntax/2html.vim204
1 files changed, 136 insertions, 68 deletions
diff --git a/runtime/syntax/2html.vim b/runtime/syntax/2html.vim
index fdee1eaf1..461b47fab 100644
--- 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: 2012 Jun 30
+" Last Change: 2013 May 31
"
" Additional contributors:
"
@@ -214,17 +214,21 @@ endif
if !s:settings.use_css
" Return opening HTML tag for given highlight id
- function! s:HtmlOpening(id)
+ function! s:HtmlOpening(id, extra_attrs)
let a = ""
if synIDattr(a:id, "inverse")
" For inverse, we always must set both colors (and exchange them)
let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
- let a = a . '<span style="background-color: ' . ( x != "" ? x : s:fgc ) . '">'
+ let a = a . '<span '.a:extra_attrs.'style="background-color: ' . ( x != "" ? x : s:fgc ) . '">'
let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
let a = a . '<font color="' . ( x != "" ? x : s:bgc ) . '">'
else
let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
- if x != "" | let a = a . '<span style="background-color: ' . x . '">' | endif
+ if x != ""
+ let a = a . '<span '.a:extra_attrs.'style="background-color: ' . x . '">'
+ elseif !empty(a:extra_attrs)
+ let a = a . '<span '.a:extra_attrs.'>'
+ endif
let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
if x != "" | let a = a . '<font color="' . x . '">' | endif
endif
@@ -235,7 +239,7 @@ if !s:settings.use_css
endfun
" Return closing HTML tag for given highlight id
- function! s:HtmlClosing(id)
+ function! s:HtmlClosing(id, has_extra_attrs)
let a = ""
if synIDattr(a:id, "underline") | let a = a . "</u>" | endif
if synIDattr(a:id, "italic") | let a = a . "</i>" | endif
@@ -246,7 +250,7 @@ if !s:settings.use_css
let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
if x != "" | let a = a . '</font>' | endif
let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
- if x != "" | let a = a . '</span>' | endif
+ if x != "" || a:has_extra_attrs | let a = a . '</span>' | endif
endif
return a
endfun
@@ -265,7 +269,7 @@ if s:settings.use_css
" first, get the style names we need
let wrapperfunc_lines = [
- \ 'function! s:BuildStyleWrapper(style_id, diff_style_id, text, make_unselectable, unformatted)',
+ \ 'function! s:BuildStyleWrapper(style_id, diff_style_id, extra_attrs, text, make_unselectable, unformatted)',
\ '',
\ ' let l:style_name = synIDattr(a:style_id, "name", s:whatterm)'
\ ]
@@ -308,7 +312,7 @@ if s:settings.use_css
let wrapperfunc_lines += [
\ '',
- \ ' if l:saved_style == ""'
+ \ ' if l:saved_style == "" && empty(a:extra_attrs)'
\ ]
if &diff
let wrapperfunc_lines += [
@@ -340,7 +344,7 @@ if s:settings.use_css
\ : "")
if s:settings.prevent_copy == ""
let wrapperfunc_lines += [
- \ ' return "<span class=\"" . l:style_name .'.diffstyle.'"\">".a:text."</span>"'
+ \ ' return "<span ".a:extra_attrs."class=\"" . l:style_name .'.diffstyle.'"\">".a:text."</span>"'
\ ]
else
@@ -362,7 +366,7 @@ if s:settings.use_css
" uses the number of unique codepoints for its limit.
let wrapperfunc_lines += [
\ ' if a:make_unselectable',
- \ ' return "<span class=\"" . l:style_name .'.diffstyle.'"\">'.
+ \ ' return "<span ".a:extra_attrs."class=\"" . l:style_name .'.diffstyle.'"\">'.
\ '<input'.s:unselInputType.' class=\"" . l:style_name .'.diffstyle.'"\"'.
\ ' value=\"".substitute(a:unformatted,''\s\+$'',"","")."\"'.
\ ' onselect=''this.blur(); return false;'''.
@@ -372,17 +376,9 @@ if s:settings.use_css
\ ' size=\"".strwidth(a:unformatted)."\"'.
\ (s:settings.use_xhtml ? '/' : '').'></span>"',
\ ' else',
- \ ' return "<span class=\"" . l:style_name .'. diffstyle .'"\">".a:text."</span>"'
+ \ ' return "<span ".a:extra_attrs."class=\"" . l:style_name .'. diffstyle .'"\">".a:text."</span>"'
\ ]
endif
- " close off tag for non-empty primary style
- if s:settings.prevent_copy == ""
- let wrapperfunc_lines[-1] .=
- \ ' "\">".a:text."</span>"'
- else
- let wrapperfunc_lines[-1] .=
- \ ' "\">".a:text."</span>"'
- endif
let wrapperfunc_lines += [
\ ' endif',
\ 'endfun'
@@ -394,16 +390,16 @@ else
" no styles exist.
if &diff
let wrapperfunc_lines = [
- \ 'function! s:BuildStyleWrapper(style_id, diff_style_id, text, unusedarg, unusedarg2)',
- \ ' return s:HtmlOpening(a:style_id).(a:diff_style_id <= 0 ? "" :'.
- \ 's:HtmlOpening(a:diff_style_id)).a:text.'.
- \ '(a:diff_style_id <= 0 ? "" : s:HtmlClosing(a:diff_style_id)).s:HtmlClosing(a:style_id)',
+ \ 'function! s:BuildStyleWrapper(style_id, diff_style_id, extra_attrs, text, unusedarg, unusedarg2)',
+ \ ' return s:HtmlOpening(a:style_id, a:extra_attrs).(a:diff_style_id <= 0 ? "" :'.
+ \ 's:HtmlOpening(a:diff_style_id, "")).a:text.'.
+ \ '(a:diff_style_id <= 0 ? "" : s:HtmlClosing(a:diff_style_id, 0)).s:HtmlClosing(a:style_id, !empty(a:extra_attrs))',
\ 'endfun'
\ ]
else
let wrapperfunc_lines = [
- \ 'function! s:BuildStyleWrapper(style_id, diff_style_id, text, unusedarg, unusedarg2)',
- \ ' return s:HtmlOpening(a:style_id).a:text.s:HtmlClosing(a:style_id)',
+ \ 'function! s:BuildStyleWrapper(style_id, diff_style_id, extra_attrs, text, unusedarg, unusedarg2)',
+ \ ' return s:HtmlOpening(a:style_id, a:extra_attrs).a:text.s:HtmlClosing(a:style_id, !empty(a:extra_attrs))',
\ 'endfun'
\ ]
endif
@@ -418,7 +414,7 @@ let s:diff_mode = &diff
" unprintable characters expanded and double spaces replaced as necessary.
"
" TODO: eliminate unneeded logic like done for BuildStyleWrapper
-function! s:HtmlFormat(text, style_id, diff_style_id, make_unselectable)
+function! s:HtmlFormat(text, style_id, diff_style_id, extra_attrs, make_unselectable)
" Replace unprintable characters
let unformatted = strtrans(a:text)
@@ -447,27 +443,45 @@ function! s:HtmlFormat(text, style_id, diff_style_id, make_unselectable)
endif
" Enclose in the correct format
- return s:BuildStyleWrapper(a:style_id, a:diff_style_id, formatted, a:make_unselectable, unformatted)
+ return s:BuildStyleWrapper(a:style_id, a:diff_style_id, a:extra_attrs, formatted, a:make_unselectable, unformatted)
endfun
" set up functions to call HtmlFormat in certain ways based on whether the
" element is supposed to be unselectable or not
if s:settings.prevent_copy =~# 'n'
- function! s:HtmlFormat_n(text, style_id, diff_style_id)
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 1)
- endfun
+ if s:settings.number_lines
+ function! s:HtmlFormat_n(text, style_id, diff_style_id, lnr)
+ if a:lnr > 0
+ return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 'id="'.(exists('g:html_diff_win_num') ? 'W'.g:html_diff_win_num : "").'L'.a:lnr.'" ', 1)
+ else
+ return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 1)
+ endif
+ endfun
+ else
+ " if lines are not being numbered the only reason this function gets called
+ " is to put the line IDs on each line; "text" will be emtpy but lnr will
+ " always be non-zero, however we don't want to use the <input> because that
+ " won't work as nice for empty text
+ function! s:HtmlFormat_n(text, style_id, diff_style_id, lnr)
+ return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 'id="'.(exists('g:html_diff_win_num') ? 'W'.g:html_diff_win_num : "").'L'.a:lnr.'" ', 0)
+ endfun
+ endif
else
- function! s:HtmlFormat_n(text, style_id, diff_style_id)
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 0)
+ function! s:HtmlFormat_n(text, style_id, diff_style_id, lnr)
+ if a:lnr > 0
+ return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 'id="'.(exists('g:html_diff_win_num') ? 'W'.g:html_diff_win_num : "").'L'.a:lnr.'" ', 0)
+ else
+ return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 0)
+ endif
endfun
endif
if s:settings.prevent_copy =~# 'd'
function! s:HtmlFormat_d(text, style_id, diff_style_id)
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 1)
+ return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 1)
endfun
else
function! s:HtmlFormat_d(text, style_id, diff_style_id)
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 0)
+ return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 0)
endfun
endif
if s:settings.prevent_copy =~# 'f'
@@ -501,7 +515,7 @@ else
\ "</a>"
endfun
function! s:FoldColumn_fill()
- return s:HtmlFormat(repeat(' ', s:foldcolumn), s:FOLD_C_ID, 0, 0)
+ return s:HtmlFormat(repeat(' ', s:foldcolumn), s:FOLD_C_ID, 0, "", 0)
endfun
endif
if s:settings.prevent_copy =~# 't'
@@ -512,17 +526,17 @@ if s:settings.prevent_copy =~# 't'
" substitute later?
if s:settings.dynamic_folds
function! s:HtmlFormat_t(text, style_id, diff_style_id)
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 1) .
- \ s:HtmlFormat("", a:style_id, 0, 0)
+ return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 1) .
+ \ s:HtmlFormat("", a:style_id, 0, "", 0)
endfun
else
function! s:HtmlFormat_t(text, style_id, diff_style_id)
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 1)
+ return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 1)
endfun
endif
else
function! s:HtmlFormat_t(text, style_id, diff_style_id)
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 0)
+ return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 0)
endfun
endif
@@ -607,7 +621,11 @@ endif
let s:orgbufnr = winbufnr(0)
let s:origwin_stl = &l:stl
if expand("%") == ""
- exec 'new Untitled.'.(s:settings.use_xhtml ? 'x' : '').'html'
+ if exists('g:html_diff_win_num')
+ exec 'new Untitled_win'.g:html_diff_win_num.'.'.(s:settings.use_xhtml ? 'x' : '').'html'
+ else
+ exec 'new Untitled.'.(s:settings.use_xhtml ? 'x' : '').'html'
+ endif
else
exec 'new %.'.(s:settings.use_xhtml ? 'x' : '').'html'
endif
@@ -625,7 +643,6 @@ setlocal winfixheight
let s:newwin_stl = &l:stl
" on the new window, set the least time-consuming fold method
-let s:old_fdm = &foldmethod
let s:old_fen = &foldenable
setlocal foldmethod=manual
setlocal nofoldenable
@@ -671,7 +688,7 @@ let s:LeadingSpace = ' '
let s:HtmlEndline = ''
if s:settings.no_pre
let s:HtmlEndline = '<br' . s:tag_close
- let s:LeadingSpace = '&nbsp;'
+ let s:LeadingSpace = s:settings.use_xhtml ? '&#160;' : '&nbsp;'
let s:HtmlSpace = '\' . s:LeadingSpace
endif
@@ -774,13 +791,12 @@ if s:settings.use_css
endif
endif
-" insert script tag if any javascript is needed
-if s:settings.dynamic_folds || s:settings.prevent_copy != ""
- call extend(s:lines, [
- \ "",
- \ "<script type='text/javascript'>",
- \ s:settings.use_xhtml ? '//<![CDATA[' : "<!--"])
-endif
+" insert script tag; javascript is always needed for the line number
+" normalization for URL hashes
+call extend(s:lines, [
+ \ "",
+ \ "<script type='text/javascript'>",
+ \ s:settings.use_xhtml ? '//<![CDATA[' : "<!--"])
" insert javascript to toggle folds open and closed
if s:settings.dynamic_folds
@@ -799,9 +815,54 @@ if s:settings.dynamic_folds
\ " fold.className = 'closed-fold';",
\ " }",
\ "}"
- \])
+ \ ])
endif
+" insert javascript to get IDs from line numbers, and to open a fold before
+" jumping to any lines contained therein
+call extend(s:lines, [
+ \ "",
+ \ "/* function to open any folds containing a jumped-to line before jumping to it */",
+ \ "function JumpToLine()",
+ \ "{",
+ \ " var lineNum;",
+ \ " lineNum = window.location.hash;",
+ \ " lineNum = lineNum.substr(1); /* strip off '#' */",
+ \ "",
+ \ " if (lineNum.indexOf('L') == -1) {",
+ \ " lineNum = 'L'+lineNum;",
+ \ " }",
+ \ " lineElem = document.getElementById(lineNum);"
+ \ ])
+if s:settings.dynamic_folds
+ call extend(s:lines, [
+ \ "",
+ \ " /* navigate upwards in the DOM tree to open all folds containing the line */",
+ \ " var node = lineElem;",
+ \ " while (node && node.id != 'vimCodeElement')",
+ \ " {",
+ \ " if (node.className == 'closed-fold')",
+ \ " {",
+ \ " node.className = 'open-fold';",
+ \ " }",
+ \ " node = node.parentNode;",
+ \ " }",
+ \ ])
+endif
+call extend(s:lines, [
+ \ " /* Always jump to new location even if the line was hidden inside a fold, or",
+ \ " * we corrected the raw number to a line ID.",
+ \ " */",
+ \ " if (lineElem) {",
+ \ " lineElem.scrollIntoView(true);",
+ \ " }",
+ \ " return true;",
+ \ "}",
+ \ "if ('onhashchange' in window) {",
+ \ " window.onhashchange = JumpToLine;",
+ \ "}"
+ \ ])
+
" Small text columns like the foldcolumn and line number column need a weird
" hack to work around Webkit's and (in versions prior to 9) IE's lack of support
" for the 'ch' unit without messing up Opera, which also doesn't support it but
@@ -861,26 +922,24 @@ if !empty(s:settings.prevent_copy)
\ ])
endif
-" insert script closing tag if any javascript is needed
-if s:settings.dynamic_folds || s:settings.prevent_copy != ""
- call extend(s:lines, [
- \ '',
- \ s:settings.use_xhtml ? '//]]>' : '-->',
- \ "</script>"
- \ ])
-endif
+" insert script closing tag
+call extend(s:lines, [
+ \ '',
+ \ s:settings.use_xhtml ? '//]]>' : '-->',
+ \ "</script>"
+ \ ])
call extend(s:lines, ["</head>"])
if !empty(s:settings.prevent_copy)
call extend(s:lines,
- \ ["<body onload='FixCharWidth();'>",
+ \ ["<body onload='FixCharWidth(); JumpToLine();'>",
\ "<!-- hidden divs used by javascript to get the width of a char -->",
\ "<div id='oneCharWidth'>0</div>",
\ "<div id='oneInputWidth'><input size='1' value='0'".s:tag_close."</div>",
\ "<div id='oneEmWidth' style='width: 1em;'></div>"
\ ])
else
- call extend(s:lines, ["<body>"])
+ call extend(s:lines, ["<body onload='JumpToLine();'>"])
endif
if s:settings.no_pre
" if we're not using CSS we use a font tag which can't have a div inside
@@ -1242,7 +1301,7 @@ while s:lnum <= s:end
if s:settings.number_lines
" Indent if line numbering is on. Indent gets style of line number
" column.
- let s:new = s:HtmlFormat_n(repeat(' ', s:margin), s:LINENR_ID, 0) . s:new
+ let s:new = s:HtmlFormat_n(repeat(' ', s:margin), s:LINENR_ID, 0, 0) . s:new
endif
if s:settings.dynamic_folds && !s:settings.no_foldcolumn && s:foldcolumn > 0
" Indent for foldcolumn if there is one. Assume it's empty, there should
@@ -1274,7 +1333,7 @@ while s:lnum <= s:end
endif
" put numcol in a separate group for sake of unselectable text
- let s:new = (s:settings.number_lines ? s:HtmlFormat_n(s:numcol, s:FOLDED_ID, 0): "") . s:HtmlFormat_t(s:new, s:FOLDED_ID, 0)
+ let s:new = (s:settings.number_lines ? s:HtmlFormat_n(s:numcol, s:FOLDED_ID, 0, s:lnum): "") . s:HtmlFormat_t(s:new, s:FOLDED_ID, 0)
" Skip to the end of the fold
let s:new_lnum = foldclosedend(s:lnum)
@@ -1355,7 +1414,7 @@ while s:lnum <= s:end
" Add fold text, moving the span ending to the next line so collapsing
" of folds works correctly.
" Put numcol in a separate group for sake of unselectable text.
- let s:new = s:new . (s:settings.number_lines ? s:HtmlFormat_n(s:numcol, s:FOLDED_ID, 0) : "") . substitute(s:HtmlFormat_t(foldtextresult(s:lnum), s:FOLDED_ID, 0), '</span>', s:HtmlEndline.'\n\0', '')
+ let s:new = s:new . (s:settings.number_lines ? s:HtmlFormat_n(s:numcol, s:FOLDED_ID, 0, 0) : "") . substitute(s:HtmlFormat_t(foldtextresult(s:lnum), s:FOLDED_ID, 0), '</span>', s:HtmlEndline.'\n\0', '')
let s:new = s:new . "<span class='fulltext'>"
" open the fold now that we have the fold text to allow retrieval of
@@ -1389,7 +1448,9 @@ while s:lnum <= s:end
" Now continue with the unfolded line text
if s:settings.number_lines
- let s:new = s:new . s:HtmlFormat_n(s:numcol, s:LINENR_ID, 0)
+ let s:new = s:new . s:HtmlFormat_n(s:numcol, s:LINENR_ID, 0, s:lnum)
+ else
+ let s:new = s:new . s:HtmlFormat_n("", s:LINENR_ID, 0, s:lnum)
endif
" Get the diff attribute, if any.
@@ -1479,7 +1540,7 @@ while s:lnum <= s:end
" Output the text with the same synID, with class set to the highlight ID
" name, unless it has been concealed completely.
if strlen(s:expandedtab) > 0
- let s:new = s:new . s:HtmlFormat(s:expandedtab, s:id, s:diff_id, 0)
+ let s:new = s:new . s:HtmlFormat(s:expandedtab, s:id, s:diff_id, "", 0)
endif
endwhile
endif
@@ -1531,6 +1592,11 @@ unlet s:lines
" stripped from the final output.
%s!\v(%(^|\s+)%(vim?|ex)):!\1\&#0058;!ge
+" The generated HTML is admittedly ugly and takes a LONG time to fold.
+" Make sure the user doesn't do syntax folding when loading a generated file,
+" using a modeline.
+call append(line('$'), "<!-- vim: set foldmethod=manual : -->")
+
" Now, when we finally know which, we define the colors and styles
if s:settings.use_css
1;/<style type="text/+1
@@ -1616,7 +1682,7 @@ if s:settings.use_css
endif
endif
else
- execute '%s:<body>:<body bgcolor="' . s:bgc . '" text="' . s:fgc . '">\r<font face="'. s:htmlfont .'">'
+ execute '%s:<body\([^>]*\):<body bgcolor="' . s:bgc . '" text="' . s:fgc . '"\1>\r<font face="'. s:htmlfont .'"'
endif
" Gather attributes for all other classes. Do diff first so that normal
@@ -1652,8 +1718,10 @@ endif
%s:\s\+$::e
" Restore old settings (new window first)
+"
+" Don't bother restoring foldmethod in case it was syntax because the markup is
+" so weirdly formatted it can take a LONG time.
let &l:foldenable = s:old_fen
-let &l:foldmethod = s:old_fdm
let &report = s:old_report
let &title = s:old_title
let &icon = s:old_icon
@@ -1684,7 +1752,7 @@ let &ls=s:ls
" Save a little bit of memory (worth doing?)
unlet s:htmlfont s:whitespace
unlet s:old_et s:old_paste s:old_icon s:old_report s:old_title s:old_search
-unlet s:old_magic s:old_more s:old_fdm s:old_fen s:old_winheight
+unlet s:old_magic s:old_more s:old_fen s:old_winheight
unlet! s:old_isprint
unlet s:whatterm s:stylelist s:diffstylelist s:lnum s:end s:margin s:fgc s:bgc s:old_winfixheight
unlet! s:col s:id s:attr s:len s:line s:new s:expandedtab s:concealinfo s:diff_mode