1" Vim autoload file for the tohtml plugin. 2" Maintainer: Ben Fritz <[email protected]> 3" Last Change: 2013 Sep 03 4" 5" Additional contributors: 6" 7" Original by Bram Moolenaar <[email protected]> 8" Diff2HTML() added by Christian Brabandt <[email protected]> 9" 10" See Mercurial change logs for more! 11 12" this file uses line continuations 13let s:cpo_sav = &cpo 14set cpo&vim 15 16" Automatically find charsets from all encodings supported natively by Vim. With 17" the 8bit- and 2byte- prefixes, Vim can actually support more encodings than 18" this. Let the user specify these however since they won't be supported on 19" every system. 20" 21" Note, not all of Vim's supported encodings have a charset to use. 22" 23" Names in this list are from: 24" http://www.iana.org/assignments/character-sets 25" g:tohtml#encoding_to_charset: {{{ 26let g:tohtml#encoding_to_charset = { 27 \ 'latin1' : 'ISO-8859-1', 28 \ 'iso-8859-2' : 'ISO-8859-2', 29 \ 'iso-8859-3' : 'ISO-8859-3', 30 \ 'iso-8859-4' : 'ISO-8859-4', 31 \ 'iso-8859-5' : 'ISO-8859-5', 32 \ 'iso-8859-6' : 'ISO-8859-6', 33 \ 'iso-8859-7' : 'ISO-8859-7', 34 \ 'iso-8859-8' : 'ISO-8859-8', 35 \ 'iso-8859-9' : 'ISO-8859-9', 36 \ 'iso-8859-10' : '', 37 \ 'iso-8859-13' : 'ISO-8859-13', 38 \ 'iso-8859-14' : '', 39 \ 'iso-8859-15' : 'ISO-8859-15', 40 \ 'koi8-r' : 'KOI8-R', 41 \ 'koi8-u' : 'KOI8-U', 42 \ 'macroman' : 'macintosh', 43 \ 'cp437' : '', 44 \ 'cp775' : '', 45 \ 'cp850' : '', 46 \ 'cp852' : '', 47 \ 'cp855' : '', 48 \ 'cp857' : '', 49 \ 'cp860' : '', 50 \ 'cp861' : '', 51 \ 'cp862' : '', 52 \ 'cp863' : '', 53 \ 'cp865' : '', 54 \ 'cp866' : 'IBM866', 55 \ 'cp869' : '', 56 \ 'cp874' : '', 57 \ 'cp1250' : 'windows-1250', 58 \ 'cp1251' : 'windows-1251', 59 \ 'cp1253' : 'windows-1253', 60 \ 'cp1254' : 'windows-1254', 61 \ 'cp1255' : 'windows-1255', 62 \ 'cp1256' : 'windows-1256', 63 \ 'cp1257' : 'windows-1257', 64 \ 'cp1258' : 'windows-1258', 65 \ 'euc-jp' : 'EUC-JP', 66 \ 'sjis' : 'Shift_JIS', 67 \ 'cp932' : 'Shift_JIS', 68 \ 'cp949' : '', 69 \ 'euc-kr' : 'EUC-KR', 70 \ 'cp936' : 'GBK', 71 \ 'euc-cn' : 'GB2312', 72 \ 'big5' : 'Big5', 73 \ 'cp950' : 'Big5', 74 \ 'utf-8' : 'UTF-8', 75 \ 'ucs-2' : 'UTF-8', 76 \ 'ucs-2le' : 'UTF-8', 77 \ 'utf-16' : 'UTF-8', 78 \ 'utf-16le' : 'UTF-8', 79 \ 'ucs-4' : 'UTF-8', 80 \ 'ucs-4le' : 'UTF-8', 81 \ } 82lockvar g:tohtml#encoding_to_charset 83" Notes: 84" 1. All UCS/UTF are converted to UTF-8 because it is much better supported 85" 2. Any blank spaces are there because Vim supports it but at least one major 86" web browser does not according to http://wiki.whatwg.org/wiki/Web_Encodings. 87" }}} 88 89" Only automatically find encodings supported natively by Vim, let the user 90" specify the encoding if it's not natively supported. This function is only 91" used when the user specifies the charset, they better know what they are 92" doing! 93" 94" Names in this list are from: 95" http://www.iana.org/assignments/character-sets 96" g:tohtml#charset_to_encoding: {{{ 97let g:tohtml#charset_to_encoding = { 98 \ 'iso_8859-1:1987' : 'latin1', 99 \ 'iso-ir-100' : 'latin1', 100 \ 'iso_8859-1' : 'latin1', 101 \ 'iso-8859-1' : 'latin1', 102 \ 'latin1' : 'latin1', 103 \ 'l1' : 'latin1', 104 \ 'ibm819' : 'latin1', 105 \ 'cp819' : 'latin1', 106 \ 'csisolatin1' : 'latin1', 107 \ 'iso_8859-2:1987' : 'iso-8859-2', 108 \ 'iso-ir-101' : 'iso-8859-2', 109 \ 'iso_8859-2' : 'iso-8859-2', 110 \ 'iso-8859-2' : 'iso-8859-2', 111 \ 'latin2' : 'iso-8859-2', 112 \ 'l2' : 'iso-8859-2', 113 \ 'csisolatin2' : 'iso-8859-2', 114 \ 'iso_8859-3:1988' : 'iso-8859-3', 115 \ 'iso-ir-109' : 'iso-8859-3', 116 \ 'iso_8859-3' : 'iso-8859-3', 117 \ 'iso-8859-3' : 'iso-8859-3', 118 \ 'latin3' : 'iso-8859-3', 119 \ 'l3' : 'iso-8859-3', 120 \ 'csisolatin3' : 'iso-8859-3', 121 \ 'iso_8859-4:1988' : 'iso-8859-4', 122 \ 'iso-ir-110' : 'iso-8859-4', 123 \ 'iso_8859-4' : 'iso-8859-4', 124 \ 'iso-8859-4' : 'iso-8859-4', 125 \ 'latin4' : 'iso-8859-4', 126 \ 'l4' : 'iso-8859-4', 127 \ 'csisolatin4' : 'iso-8859-4', 128 \ 'iso_8859-5:1988' : 'iso-8859-5', 129 \ 'iso-ir-144' : 'iso-8859-5', 130 \ 'iso_8859-5' : 'iso-8859-5', 131 \ 'iso-8859-5' : 'iso-8859-5', 132 \ 'cyrillic' : 'iso-8859-5', 133 \ 'csisolatincyrillic' : 'iso-8859-5', 134 \ 'iso_8859-6:1987' : 'iso-8859-6', 135 \ 'iso-ir-127' : 'iso-8859-6', 136 \ 'iso_8859-6' : 'iso-8859-6', 137 \ 'iso-8859-6' : 'iso-8859-6', 138 \ 'ecma-114' : 'iso-8859-6', 139 \ 'asmo-708' : 'iso-8859-6', 140 \ 'arabic' : 'iso-8859-6', 141 \ 'csisolatinarabic' : 'iso-8859-6', 142 \ 'iso_8859-7:1987' : 'iso-8859-7', 143 \ 'iso-ir-126' : 'iso-8859-7', 144 \ 'iso_8859-7' : 'iso-8859-7', 145 \ 'iso-8859-7' : 'iso-8859-7', 146 \ 'elot_928' : 'iso-8859-7', 147 \ 'ecma-118' : 'iso-8859-7', 148 \ 'greek' : 'iso-8859-7', 149 \ 'greek8' : 'iso-8859-7', 150 \ 'csisolatingreek' : 'iso-8859-7', 151 \ 'iso_8859-8:1988' : 'iso-8859-8', 152 \ 'iso-ir-138' : 'iso-8859-8', 153 \ 'iso_8859-8' : 'iso-8859-8', 154 \ 'iso-8859-8' : 'iso-8859-8', 155 \ 'hebrew' : 'iso-8859-8', 156 \ 'csisolatinhebrew' : 'iso-8859-8', 157 \ 'iso_8859-9:1989' : 'iso-8859-9', 158 \ 'iso-ir-148' : 'iso-8859-9', 159 \ 'iso_8859-9' : 'iso-8859-9', 160 \ 'iso-8859-9' : 'iso-8859-9', 161 \ 'latin5' : 'iso-8859-9', 162 \ 'l5' : 'iso-8859-9', 163 \ 'csisolatin5' : 'iso-8859-9', 164 \ 'iso-8859-10' : 'iso-8859-10', 165 \ 'iso-ir-157' : 'iso-8859-10', 166 \ 'l6' : 'iso-8859-10', 167 \ 'iso_8859-10:1992' : 'iso-8859-10', 168 \ 'csisolatin6' : 'iso-8859-10', 169 \ 'latin6' : 'iso-8859-10', 170 \ 'iso-8859-13' : 'iso-8859-13', 171 \ 'iso-8859-14' : 'iso-8859-14', 172 \ 'iso-ir-199' : 'iso-8859-14', 173 \ 'iso_8859-14:1998' : 'iso-8859-14', 174 \ 'iso_8859-14' : 'iso-8859-14', 175 \ 'latin8' : 'iso-8859-14', 176 \ 'iso-celtic' : 'iso-8859-14', 177 \ 'l8' : 'iso-8859-14', 178 \ 'iso-8859-15' : 'iso-8859-15', 179 \ 'iso_8859-15' : 'iso-8859-15', 180 \ 'latin-9' : 'iso-8859-15', 181 \ 'koi8-r' : 'koi8-r', 182 \ 'cskoi8r' : 'koi8-r', 183 \ 'koi8-u' : 'koi8-u', 184 \ 'macintosh' : 'macroman', 185 \ 'mac' : 'macroman', 186 \ 'csmacintosh' : 'macroman', 187 \ 'ibm437' : 'cp437', 188 \ 'cp437' : 'cp437', 189 \ '437' : 'cp437', 190 \ 'cspc8codepage437' : 'cp437', 191 \ 'ibm775' : 'cp775', 192 \ 'cp775' : 'cp775', 193 \ 'cspc775baltic' : 'cp775', 194 \ 'ibm850' : 'cp850', 195 \ 'cp850' : 'cp850', 196 \ '850' : 'cp850', 197 \ 'cspc850multilingual' : 'cp850', 198 \ 'ibm852' : 'cp852', 199 \ 'cp852' : 'cp852', 200 \ '852' : 'cp852', 201 \ 'cspcp852' : 'cp852', 202 \ 'ibm855' : 'cp855', 203 \ 'cp855' : 'cp855', 204 \ '855' : 'cp855', 205 \ 'csibm855' : 'cp855', 206 \ 'ibm857' : 'cp857', 207 \ 'cp857' : 'cp857', 208 \ '857' : 'cp857', 209 \ 'csibm857' : 'cp857', 210 \ 'ibm860' : 'cp860', 211 \ 'cp860' : 'cp860', 212 \ '860' : 'cp860', 213 \ 'csibm860' : 'cp860', 214 \ 'ibm861' : 'cp861', 215 \ 'cp861' : 'cp861', 216 \ '861' : 'cp861', 217 \ 'cp-is' : 'cp861', 218 \ 'csibm861' : 'cp861', 219 \ 'ibm862' : 'cp862', 220 \ 'cp862' : 'cp862', 221 \ '862' : 'cp862', 222 \ 'cspc862latinhebrew' : 'cp862', 223 \ 'ibm863' : 'cp863', 224 \ 'cp863' : 'cp863', 225 \ '863' : 'cp863', 226 \ 'csibm863' : 'cp863', 227 \ 'ibm865' : 'cp865', 228 \ 'cp865' : 'cp865', 229 \ '865' : 'cp865', 230 \ 'csibm865' : 'cp865', 231 \ 'ibm866' : 'cp866', 232 \ 'cp866' : 'cp866', 233 \ '866' : 'cp866', 234 \ 'csibm866' : 'cp866', 235 \ 'ibm869' : 'cp869', 236 \ 'cp869' : 'cp869', 237 \ '869' : 'cp869', 238 \ 'cp-gr' : 'cp869', 239 \ 'csibm869' : 'cp869', 240 \ 'windows-1250' : 'cp1250', 241 \ 'windows-1251' : 'cp1251', 242 \ 'windows-1253' : 'cp1253', 243 \ 'windows-1254' : 'cp1254', 244 \ 'windows-1255' : 'cp1255', 245 \ 'windows-1256' : 'cp1256', 246 \ 'windows-1257' : 'cp1257', 247 \ 'windows-1258' : 'cp1258', 248 \ 'extended_unix_code_packed_format_for_japanese' : 'euc-jp', 249 \ 'cseucpkdfmtjapanese' : 'euc-jp', 250 \ 'euc-jp' : 'euc-jp', 251 \ 'shift_jis' : 'sjis', 252 \ 'ms_kanji' : 'sjis', 253 \ 'sjis' : 'sjis', 254 \ 'csshiftjis' : 'sjis', 255 \ 'ibm-thai' : 'cp874', 256 \ 'csibmthai' : 'cp874', 257 \ 'ks_c_5601-1987' : 'cp949', 258 \ 'iso-ir-149' : 'cp949', 259 \ 'ks_c_5601-1989' : 'cp949', 260 \ 'ksc_5601' : 'cp949', 261 \ 'korean' : 'cp949', 262 \ 'csksc56011987' : 'cp949', 263 \ 'euc-kr' : 'euc-kr', 264 \ 'cseuckr' : 'euc-kr', 265 \ 'gbk' : 'cp936', 266 \ 'cp936' : 'cp936', 267 \ 'ms936' : 'cp936', 268 \ 'windows-936' : 'cp936', 269 \ 'gb_2312-80' : 'euc-cn', 270 \ 'iso-ir-58' : 'euc-cn', 271 \ 'chinese' : 'euc-cn', 272 \ 'csiso58gb231280' : 'euc-cn', 273 \ 'big5' : 'big5', 274 \ 'csbig5' : 'big5', 275 \ 'utf-8' : 'utf-8', 276 \ 'iso-10646-ucs-2' : 'ucs-2', 277 \ 'csunicode' : 'ucs-2', 278 \ 'utf-16' : 'utf-16', 279 \ 'utf-16be' : 'utf-16', 280 \ 'utf-16le' : 'utf-16le', 281 \ 'utf-32' : 'ucs-4', 282 \ 'utf-32be' : 'ucs-4', 283 \ 'utf-32le' : 'ucs-4le', 284 \ 'iso-10646-ucs-4' : 'ucs-4', 285 \ 'csucs4' : 'ucs-4' 286 \ } 287lockvar g:tohtml#charset_to_encoding 288"}}} 289 290func! tohtml#Convert2HTML(line1, line2) "{{{ 291 let s:settings = tohtml#GetUserSettings() 292 293 if !&diff || s:settings.diff_one_file "{{{ 294 if a:line2 >= a:line1 295 let g:html_start_line = a:line1 296 let g:html_end_line = a:line2 297 else 298 let g:html_start_line = a:line2 299 let g:html_end_line = a:line1 300 endif 301 runtime syntax/2html.vim "}}} 302 else "{{{ 303 let win_list = [] 304 let buf_list = [] 305 windo if &diff | call add(win_list, winbufnr(0)) | endif 306 let s:settings.whole_filler = 1 307 let g:html_diff_win_num = 0 308 for window in win_list 309 " switch to the next buffer to convert 310 exe ":" . bufwinnr(window) . "wincmd w" 311 312 " figure out whether current charset and encoding will work, if not 313 " default to UTF-8 314 if !exists('g:html_use_encoding') && 315 \ (((&l:fileencoding=='' || (&l:buftype!='' && &l:buftype!=?'help')) 316 \ && &encoding!=?s:settings.vim_encoding) 317 \ || &l:fileencoding!='' && &l:fileencoding!=?s:settings.vim_encoding) 318 echohl WarningMsg 319 echomsg "TOhtml: mismatched file encodings in Diff buffers, using UTF-8" 320 echohl None 321 let s:settings.vim_encoding = 'utf-8' 322 let s:settings.encoding = 'UTF-8' 323 endif 324 325 " set up for diff-mode conversion 326 let g:html_start_line = 1 327 let g:html_end_line = line('$') 328 let g:html_diff_win_num += 1 329 330 " convert this file 331 runtime syntax/2html.vim 332 333 " remember the HTML buffer for later combination 334 call add(buf_list, bufnr('%')) 335 endfor 336 unlet g:html_diff_win_num 337 call tohtml#Diff2HTML(win_list, buf_list) 338 endif "}}} 339 340 unlet g:html_start_line 341 unlet g:html_end_line 342 unlet s:settings 343endfunc "}}} 344 345func! tohtml#Diff2HTML(win_list, buf_list) "{{{ 346 let xml_line = "" 347 let tag_close = '>' 348 349 let s:old_paste = &paste 350 set paste 351 let s:old_magic = &magic 352 set magic 353 354 if s:settings.use_xhtml 355 if s:settings.encoding != "" 356 let xml_line = "<?xml version=\"1.0\" encoding=\"" . s:settings.encoding . "\"?>" 357 else 358 let xml_line = "<?xml version=\"1.0\"?>" 359 endif 360 let tag_close = ' />' 361 endif 362 363 let style = [s:settings.use_xhtml ? "" : '-->'] 364 let body_line = '' 365 366 let html = [] 367 if s:settings.use_xhtml 368 call add(html, xml_line) 369 endif 370 if s:settings.use_xhtml 371 call add(html, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">") 372 call add(html, '<html xmlns="http://www.w3.org/1999/xhtml">') 373 elseif s:settings.use_css && !s:settings.no_pre 374 call add(html, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">") 375 call add(html, '<html>') 376 else 377 call add(html, '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"') 378 call add(html, ' "http://www.w3.org/TR/html4/loose.dtd">') 379 call add(html, '<html>') 380 endif 381 call add(html, '<head>') 382 383 " include encoding as close to the top as possible, but only if not already 384 " contained in XML information 385 if s:settings.encoding != "" && !s:settings.use_xhtml 386 call add(html, "<meta http-equiv=\"content-type\" content=\"text/html; charset=" . s:settings.encoding . '"' . tag_close) 387 endif 388 389 call add(html, '<title>diff</title>') 390 call add(html, '<meta name="Generator" content="Vim/'.v:version/100.'.'.v:version%100.'"'.tag_close) 391 call add(html, '<meta name="plugin-version" content="'.g:loaded_2html_plugin.'"'.tag_close) 392 call add(html, '<meta name="settings" content="'. 393 \ join(filter(keys(s:settings),'s:settings[v:val]'),','). 394 \ ',prevent_copy='.s:settings.prevent_copy. 395 \ '"'.tag_close) 396 call add(html, '<meta name="colorscheme" content="'. 397 \ (exists('g:colors_name') 398 \ ? g:colors_name 399 \ : 'none'). '"'.tag_close) 400 401 call add(html, '</head>') 402 let body_line_num = len(html) 403 if !empty(s:settings.prevent_copy) 404 call add(html, "<body onload='FixCharWidth();".(s:settings.line_ids ? " JumpToLine();" : "")."'>") 405 call add(html, "<!-- hidden divs used by javascript to get the width of a char -->") 406 call add(html, "<div id='oneCharWidth'>0</div>") 407 call add(html, "<div id='oneInputWidth'><input size='1' value='0'".tag_close."</div>") 408 call add(html, "<div id='oneEmWidth' style='width: 1em;'></div>") 409 else 410 call add(html, '<body'.(s:settings.line_ids ? ' onload="JumpToLine();"' : '').'>') 411 endif 412 call add(html, "<table border='1' width='100%' id='vimCodeElement".s:settings.id_suffix."'>") 413 414 call add(html, '<tr>') 415 for buf in a:win_list 416 call add(html, '<th>'.bufname(buf).'</th>') 417 endfor 418 call add(html, '</tr><tr>') 419 420 let diff_style_start = 0 421 let insert_index = 0 422 423 for buf in a:buf_list 424 let temp = [] 425 exe bufwinnr(buf) . 'wincmd w' 426 427 " If text is folded because of user foldmethod settings, etc. we don't want 428 " to act on everything in a fold by mistake. 429 setlocal nofoldenable 430 431 " When not using CSS or when using xhtml, the <body> line can be important. 432 " Assume it will be the same for all buffers and grab it from the first 433 " buffer. Similarly, need to grab the body end line as well. 434 if body_line == '' 435 1 436 call search('<body') 437 let body_line = getline('.') 438 $ 439 call search('</body>', 'b') 440 let s:body_end_line = getline('.') 441 endif 442 443 " Grab the style information. Some of this will be duplicated so only insert 444 " it if it's not already there. {{{ 445 1 446 let style_start = search('^<style type="text/css">') 447 1 448 let style_end = search('^</style>') 449 if style_start > 0 && style_end > 0 450 let buf_styles = getline(style_start + 1, style_end - 1) 451 for a_style in buf_styles 452 if index(style, a_style) == -1 453 if diff_style_start == 0 454 if a_style =~ '\<Diff\(Change\|Text\|Add\|Delete\)' 455 let diff_style_start = len(style)-1 456 endif 457 endif 458 call insert(style, a_style, insert_index) 459 let insert_index += 1 460 endif 461 endfor 462 endif " }}} 463 464 " everything new will get added before the diff styles so diff highlight 465 " properly overrides normal highlight 466 if diff_style_start != 0 467 let insert_index = diff_style_start 468 endif 469 470 " Delete those parts that are not needed so we can include the rest into the 471 " resulting table. 472 1,/^<body.*\%(\n<!--.*-->\_s\+.*id='oneCharWidth'.*\_s\+.*id='oneInputWidth'.*\_s\+.*id='oneEmWidth'\)\?\zs/d_ 473 $ 474 ?</body>?,$d_ 475 let temp = getline(1,'$') 476 " clean out id on the main content container because we already set it on 477 " the table 478 let temp[0] = substitute(temp[0], " id='vimCodeElement[^']*'", "", "") 479 " undo deletion of start and end part 480 " so we can later save the file as valid html 481 " TODO: restore using grabbed lines if undolevel is 1? 482 normal! 2u 483 if s:settings.use_css 484 call add(html, '<td valign="top"><div>') 485 elseif s:settings.use_xhtml 486 call add(html, '<td nowrap="nowrap" valign="top"><div>') 487 else 488 call add(html, '<td nowrap valign="top"><div>') 489 endif 490 let html += temp 491 call add(html, '</div></td>') 492 493 " Close this buffer 494 " TODO: the comment above says we're going to allow saving the file 495 " later...but here we discard it? 496 quit! 497 endfor 498 499 let html[body_line_num] = body_line 500 501 call add(html, '</tr>') 502 call add(html, '</table>') 503 call add(html, s:body_end_line) 504 call add(html, '</html>') 505 506 " The generated HTML is admittedly ugly and takes a LONG time to fold. 507 " Make sure the user doesn't do syntax folding when loading a generated file, 508 " using a modeline. 509 call add(html, '<!-- vim: set foldmethod=manual : -->') 510 511 let i = 1 512 let name = "Diff" . (s:settings.use_xhtml ? ".xhtml" : ".html") 513 " Find an unused file name if current file name is already in use 514 while filereadable(name) 515 let name = substitute(name, '\d*\.x\?html$', '', '') . i . '.' . fnamemodify(copy(name), ":t:e") 516 let i += 1 517 endwhile 518 exe "topleft new " . name 519 setlocal modifiable 520 521 " just in case some user autocmd creates content in the new buffer, make sure 522 " it is empty before proceeding 523 %d 524 525 " set the fileencoding to match the charset we'll be using 526 let &l:fileencoding=s:settings.vim_encoding 527 528 " According to http://www.w3.org/TR/html4/charset.html#doc-char-set, the byte 529 " order mark is highly recommend on the web when using multibyte encodings. But, 530 " it is not a good idea to include it on UTF-8 files. Otherwise, let Vim 531 " determine when it is actually inserted. 532 if s:settings.vim_encoding == 'utf-8' 533 setlocal nobomb 534 else 535 setlocal bomb 536 endif 537 538 call append(0, html) 539 540 if len(style) > 0 541 1 542 let style_start = search('^</head>')-1 543 544 " add required javascript in reverse order so we can just call append again 545 " and again without adjusting {{{ 546 547 " insert script closing tag 548 call append(style_start, [ 549 \ '', 550 \ s:settings.use_xhtml ? '//]]>' : '-->', 551 \ "</script>" 552 \ ]) 553 554 " insert script which corrects the size of small input elements in 555 " prevent_copy mode. See 2html.vim for details on why this is needed and how 556 " it works. 557 if !empty(s:settings.prevent_copy) 558 call append(style_start, [ 559 \ '', 560 \ '/* simulate a "ch" unit by asking the browser how big a zero character is */', 561 \ 'function FixCharWidth() {', 562 \ ' /* get the hidden element which gives the width of a single character */', 563 \ ' var goodWidth = document.getElementById("oneCharWidth").clientWidth;', 564 \ ' /* get all input elements, we''ll filter on class later */', 565 \ ' var inputTags = document.getElementsByTagName("input");', 566 \ ' var ratio = 5;', 567 \ ' var inputWidth = document.getElementById("oneInputWidth").clientWidth;', 568 \ ' var emWidth = document.getElementById("oneEmWidth").clientWidth;', 569 \ ' if (inputWidth > goodWidth) {', 570 \ ' while (ratio < 100*goodWidth/emWidth && ratio < 100) {', 571 \ ' ratio += 5;', 572 \ ' }', 573 \ ' document.getElementById("vimCodeElement'.s:settings.id_suffix.'").className = "em"+ratio;', 574 \ ' }', 575 \ '}' 576 \ ]) 577 endif 578 " 579 " insert javascript to get IDs from line numbers, and to open a fold before 580 " jumping to any lines contained therein 581 call append(style_start, [ 582 \ " /* Always jump to new location even if the line was hidden inside a fold, or", 583 \ " * we corrected the raw number to a line ID.", 584 \ " */", 585 \ " if (lineElem) {", 586 \ " lineElem.scrollIntoView(true);", 587 \ " }", 588 \ " return true;", 589 \ "}", 590 \ "if ('onhashchange' in window) {", 591 \ " window.onhashchange = JumpToLine;", 592 \ "}" 593 \ ]) 594 if s:settings.dynamic_folds 595 call append(style_start, [ 596 \ "", 597 \ " /* navigate upwards in the DOM tree to open all folds containing the line */", 598 \ " var node = lineElem;", 599 \ " while (node && node.id != 'vimCodeElement".s:settings.id_suffix."')", 600 \ " {", 601 \ " if (node.className == 'closed-fold')", 602 \ " {", 603 \ " /* toggle open the fold ID (remove window ID) */", 604 \ " toggleFold(node.id.substr(4));", 605 \ " }", 606 \ " node = node.parentNode;", 607 \ " }", 608 \ ]) 609 endif 610 call append(style_start, [ 611 \ "", 612 \ "/* function to open any folds containing a jumped-to line before jumping to it */", 613 \ "function JumpToLine()", 614 \ "{", 615 \ " var lineNum;", 616 \ " lineNum = window.location.hash;", 617 \ " lineNum = lineNum.substr(1); /* strip off '#' */", 618 \ "", 619 \ " if (lineNum.indexOf('L') == -1) {", 620 \ " lineNum = 'L'+lineNum;", 621 \ " }", 622 \ " if (lineNum.indexOf('W') == -1) {", 623 \ " lineNum = 'W1'+lineNum;", 624 \ " }", 625 \ " lineElem = document.getElementById(lineNum);" 626 \ ]) 627 628 " Insert javascript to toggle matching folds open and closed in all windows, 629 " if dynamic folding is active. 630 if s:settings.dynamic_folds 631 call append(style_start, [ 632 \ " function toggleFold(objID)", 633 \ " {", 634 \ " for (win_num = 1; win_num <= ".len(a:buf_list)."; win_num++)", 635 \ " {", 636 \ " var fold;", 637 \ ' fold = document.getElementById("win"+win_num+objID);', 638 \ " if(fold.className == 'closed-fold')", 639 \ " {", 640 \ " fold.className = 'open-fold';", 641 \ " }", 642 \ " else if (fold.className == 'open-fold')", 643 \ " {", 644 \ " fold.className = 'closed-fold';", 645 \ " }", 646 \ " }", 647 \ " }", 648 \ ]) 649 endif 650 651 " insert script tag; javascript is always needed for the line number 652 " normalization for URL hashes 653 call append(style_start, [ 654 \ "<script type='text/javascript'>", 655 \ s:settings.use_xhtml ? '//<![CDATA[' : "<!--"]) 656 657 " Insert styles from all the generated html documents and additional styles 658 " for the table-based layout of the side-by-side diff. The diff should take 659 " up the full browser window (but not more), and be static in size, 660 " horizontally scrollable when the lines are too long. Otherwise, the diff 661 " is pretty useless for really long lines. {{{ 662 if s:settings.use_css 663 call append(style_start, 664 \ ['<style type="text/css">']+ 665 \ style+ 666 \ [ s:settings.use_xhtml ? '' : '<!--', 667 \ 'table { table-layout: fixed; }', 668 \ 'html, body, table, tbody { width: 100%; margin: 0; padding: 0; }', 669 \ 'th, td { width: '.printf("%.1f",100.0/len(a:win_list)).'%; }', 670 \ 'td div { overflow: auto; }', 671 \ s:settings.use_xhtml ? '' : '-->', 672 \ '</style>' 673 \]) 674 endif "}}} 675 endif 676 677 let &paste = s:old_paste 678 let &magic = s:old_magic 679endfunc "}}} 680 681" Gets a single user option and sets it in the passed-in Dict, or gives it the 682" default value if the option doesn't actually exist. 683func! tohtml#GetOption(settings, option, default) "{{{ 684 if exists('g:html_'.a:option) 685 let a:settings[a:option] = g:html_{a:option} 686 else 687 let a:settings[a:option] = a:default 688 endif 689endfunc "}}} 690 691" returns a Dict containing the values of all user options for 2html, including 692" default values for those not given an explicit value by the user. Discards the 693" html_ prefix of the option for nicer looking code. 694func! tohtml#GetUserSettings() "{{{ 695 if exists('s:settings') 696 " just restore the known options if we've already retrieved them 697 return s:settings 698 else 699 " otherwise figure out which options are set 700 let user_settings = {} 701 702 " Define the correct option if the old option name exists and we haven't 703 " already defined the correct one. Maybe I'll put out a warnig message about 704 " this sometime and remove the old option entirely at some even later time, 705 " but for now just silently accept the old option. 706 if exists('g:use_xhtml') && !exists("g:html_use_xhtml") 707 let g:html_use_xhtml = g:use_xhtml 708 endif 709 710 " get current option settings with appropriate defaults {{{ 711 call tohtml#GetOption(user_settings, 'no_progress', !has("statusline") ) 712 call tohtml#GetOption(user_settings, 'diff_one_file', 0 ) 713 call tohtml#GetOption(user_settings, 'number_lines', &number ) 714 call tohtml#GetOption(user_settings, 'pre_wrap', &wrap ) 715 call tohtml#GetOption(user_settings, 'use_css', 1 ) 716 call tohtml#GetOption(user_settings, 'ignore_conceal', 0 ) 717 call tohtml#GetOption(user_settings, 'ignore_folding', 0 ) 718 call tohtml#GetOption(user_settings, 'dynamic_folds', 0 ) 719 call tohtml#GetOption(user_settings, 'no_foldcolumn', user_settings.ignore_folding) 720 call tohtml#GetOption(user_settings, 'hover_unfold', 0 ) 721 call tohtml#GetOption(user_settings, 'no_pre', 0 ) 722 call tohtml#GetOption(user_settings, 'no_invalid', 0 ) 723 call tohtml#GetOption(user_settings, 'whole_filler', 0 ) 724 call tohtml#GetOption(user_settings, 'use_xhtml', 0 ) 725 call tohtml#GetOption(user_settings, 'line_ids', user_settings.number_lines ) 726 " }}} 727 728 " override those settings that need it {{{ 729 730 " hover opening implies dynamic folding 731 if user_settings.hover_unfold 732 let user_settings.dynamic_folds = 1 733 endif 734 735 " ignore folding overrides dynamic folding 736 if user_settings.ignore_folding && user_settings.dynamic_folds 737 let user_settings.dynamic_folds = 0 738 let user_settings.hover_unfold = 0 739 endif 740 741 " dynamic folding with no foldcolumn implies hover opens 742 if user_settings.dynamic_folds && user_settings.no_foldcolumn 743 let user_settings.hover_unfold = 1 744 endif 745 746 " dynamic folding implies css 747 if user_settings.dynamic_folds 748 let user_settings.use_css = 1 749 else 750 let user_settings.no_foldcolumn = 1 " won't do anything but for consistency and for the test suite 751 endif 752 753 " if we're not using CSS we cannot use a pre section because <font> tags 754 " aren't allowed inside a <pre> block 755 if !user_settings.use_css 756 let user_settings.no_pre = 1 757 endif 758 759 " pre_wrap doesn't do anything if not using pre or not using CSS 760 if user_settings.no_pre || !user_settings.use_css 761 let user_settings.pre_wrap=0 762 endif 763 "}}} 764 765 " set up expand_tabs option after all the overrides so we know the 766 " appropriate defaults {{{ 767 if user_settings.no_pre == 0 768 call tohtml#GetOption(user_settings, 769 \ 'expand_tabs', 770 \ &expandtab || &ts != 8 || user_settings.number_lines || 771 \ (user_settings.dynamic_folds && !user_settings.no_foldcolumn)) 772 else 773 let user_settings.expand_tabs = 1 774 endif 775 " }}} 776 777 " textual options 778 if exists("g:html_use_encoding") "{{{ 779 " user specified the desired MIME charset, figure out proper 780 " 'fileencoding' from it or warn the user if we cannot 781 let user_settings.encoding = g:html_use_encoding 782 let user_settings.vim_encoding = tohtml#EncodingFromCharset(g:html_use_encoding) 783 if user_settings.vim_encoding == '' 784 echohl WarningMsg 785 echomsg "TOhtml: file encoding for" 786 \ g:html_use_encoding 787 \ "unknown, please set 'fileencoding'" 788 echohl None 789 endif 790 else 791 " Figure out proper MIME charset from 'fileencoding' if possible 792 if &l:fileencoding != '' 793 " If the buffer is not a "normal" type, the 'fileencoding' value may not 794 " be trusted; since the buffer should not be written the fileencoding is 795 " not intended to be used. 796 if &l:buftype=='' || &l:buftype==?'help' 797 let user_settings.vim_encoding = &l:fileencoding 798 call tohtml#CharsetFromEncoding(user_settings) 799 else 800 let user_settings.encoding = '' " trigger detection using &encoding 801 endif 802 endif 803 804 " else from 'encoding' if possible 805 if &l:fileencoding == '' || user_settings.encoding == '' 806 let user_settings.vim_encoding = &encoding 807 call tohtml#CharsetFromEncoding(user_settings) 808 endif 809 810 " else default to UTF-8 and warn user 811 if user_settings.encoding == '' 812 let user_settings.vim_encoding = 'utf-8' 813 let user_settings.encoding = 'UTF-8' 814 echohl WarningMsg 815 echomsg "TOhtml: couldn't determine MIME charset, using UTF-8" 816 echohl None 817 endif 818 endif "}}} 819 820 " Default to making nothing uncopyable, because we default to 821 " not-standards way of doing things, and also because Microsoft Word and 822 " others paste the <input> elements anyway. 823 " 824 " html_prevent_copy only has an effect when using CSS. 825 " 826 " All options: 827 " f - fold column 828 " n - line numbers (also within fold text) 829 " t - fold text 830 " d - diff filler 831 " c - concealed text (reserved future) 832 " l - listchars (reserved possible future) 833 " s - signs (reserved possible future) 834 " 835 " Normal text is always selectable. 836 let user_settings.prevent_copy = "" 837 if user_settings.use_css 838 if exists("g:html_prevent_copy") 839 if user_settings.dynamic_folds && !user_settings.no_foldcolumn && g:html_prevent_copy =~# 'f' 840 let user_settings.prevent_copy .= 'f' 841 endif 842 if user_settings.number_lines && g:html_prevent_copy =~# 'n' 843 let user_settings.prevent_copy .= 'n' 844 endif 845 if &diff && g:html_prevent_copy =~# 'd' 846 let user_settings.prevent_copy .= 'd' 847 endif 848 if !user_settings.ignore_folding && g:html_prevent_copy =~# 't' 849 let user_settings.prevent_copy .= 't' 850 endif 851 else 852 let user_settings.prevent_copy = "" 853 endif 854 endif 855 if empty(user_settings.prevent_copy) 856 let user_settings.no_invalid = 0 857 endif 858 859 if exists('g:html_id_expr') 860 let user_settings.id_suffix = eval(g:html_id_expr) 861 if user_settings.id_suffix !~ '^[-_:.A-Za-z0-9]*$' 862 echohl WarningMsg 863 echomsg '2html: g:html_id_expr evaluated to invalid string for HTML id attributes' 864 echomsg '2html: Omitting user-specified suffix' 865 echohl None 866 sleep 3 867 let user_settings.id_suffix="" 868 endif 869 else 870 let user_settings.id_suffix="" 871 endif 872 873 " TODO: font 874 875 return user_settings 876 endif 877endfunc "}}} 878 879" get the proper HTML charset name from a Vim encoding option. 880function! tohtml#CharsetFromEncoding(settings) "{{{ 881 let l:vim_encoding = a:settings.vim_encoding 882 if exists('g:html_charset_override') && has_key(g:html_charset_override, l:vim_encoding) 883 let a:settings.encoding = g:html_charset_override[l:vim_encoding] 884 else 885 if l:vim_encoding =~ '^8bit\|^2byte' 886 " 8bit- and 2byte- prefixes are to indicate encodings available on the 887 " system that Vim will convert with iconv(), look up just the encoding name, 888 " not Vim's prefix. 889 let l:vim_encoding = substitute(l:vim_encoding, '^8bit-\|^2byte-', '', '') 890 endif 891 if has_key(g:tohtml#encoding_to_charset, l:vim_encoding) 892 let a:settings.encoding = g:tohtml#encoding_to_charset[l:vim_encoding] 893 else 894 let a:settings.encoding = "" 895 endif 896 endif 897 if a:settings.encoding != "" 898 let l:vim_encoding = tohtml#EncodingFromCharset(a:settings.encoding) 899 if l:vim_encoding != "" 900 " if the Vim encoding to HTML encoding conversion is set up (by default or 901 " by the user) to convert to a different encoding, we need to also change 902 " the Vim encoding of the new buffer 903 let a:settings.vim_encoding = l:vim_encoding 904 endif 905 endif 906endfun "}}} 907 908" Get the proper Vim encoding option setting from an HTML charset name. 909function! tohtml#EncodingFromCharset(encoding) "{{{ 910 if exists('g:html_encoding_override') && has_key(g:html_encoding_override, a:encoding) 911 return g:html_encoding_override[a:encoding] 912 elseif has_key(g:tohtml#charset_to_encoding, tolower(a:encoding)) 913 return g:tohtml#charset_to_encoding[tolower(a:encoding)] 914 else 915 return "" 916 endif 917endfun "}}} 918 919let &cpo = s:cpo_sav 920unlet s:cpo_sav 921 922" Make sure any patches will probably use consistent indent 923" vim: ts=8 sw=2 sts=2 noet fdm=marker 924