1" Vim autoload file for the tohtml plugin. 2" Maintainer: Ben Fritz <[email protected]> 3" Last Change: 2019 Aug 16 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 let s:html5 = 0 368 if s:settings.use_xhtml 369 call add(html, xml_line) 370 endif 371 if s:settings.use_xhtml 372 call add(html, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">") 373 call add(html, '<html xmlns="http://www.w3.org/1999/xhtml">') 374 elseif s:settings.use_css && !s:settings.no_pre 375 call add(html, "<!DOCTYPE html>") 376 call add(html, '<html>') 377 let s:html5 = 1 378 else 379 call add(html, '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"') 380 call add(html, ' "http://www.w3.org/TR/html4/loose.dtd">') 381 call add(html, '<html>') 382 endif 383 call add(html, '<head>') 384 385 " include encoding as close to the top as possible, but only if not already 386 " contained in XML information 387 if s:settings.encoding != "" && !s:settings.use_xhtml 388 if s:html5 389 call add(html, '<meta charset="' . s:settings.encoding . '"' . tag_close) 390 else 391 call add(html, "<meta http-equiv=\"content-type\" content=\"text/html; charset=" . s:settings.encoding . '"' . tag_close) 392 endif 393 endif 394 395 call add(html, '<title>diff</title>') 396 call add(html, '<meta name="Generator" content="Vim/'.v:version/100.'.'.v:version%100.'"'.tag_close) 397 call add(html, '<meta name="plugin-version" content="'.g:loaded_2html_plugin.'"'.tag_close) 398 call add(html, '<meta name="settings" content="'. 399 \ join(filter(keys(s:settings),'s:settings[v:val]'),','). 400 \ ',prevent_copy='.s:settings.prevent_copy. 401 \ ',use_input_for_pc='.s:settings.use_input_for_pc. 402 \ '"'.tag_close) 403 call add(html, '<meta name="colorscheme" content="'. 404 \ (exists('g:colors_name') 405 \ ? g:colors_name 406 \ : 'none'). '"'.tag_close) 407 408 call add(html, '</head>') 409 let body_line_num = len(html) 410 call add(html, '<body'.(s:settings.line_ids ? ' onload="JumpToLine();"' : '').'>') 411 call add(html, "<table ".(s:settings.use_css? "" : "border='1' width='100%' ")."id='vimCodeElement".s:settings.id_suffix."'>") 412 413 call add(html, '<tr>') 414 for buf in a:win_list 415 call add(html, '<th>'.bufname(buf).'</th>') 416 endfor 417 call add(html, '</tr><tr>') 418 419 let diff_style_start = 0 420 let insert_index = 0 421 422 for buf in a:buf_list 423 let temp = [] 424 exe bufwinnr(buf) . 'wincmd w' 425 426 " If text is folded because of user foldmethod settings, etc. we don't want 427 " to act on everything in a fold by mistake. 428 setlocal nofoldenable 429 430 " When not using CSS or when using xhtml, the <body> line can be important. 431 " Assume it will be the same for all buffers and grab it from the first 432 " buffer. Similarly, need to grab the body end line as well. 433 if body_line == '' 434 1 435 call search('<body') 436 let body_line = getline('.') 437 $ 438 call search('</body>', 'b') 439 let s:body_end_line = getline('.') 440 endif 441 442 " Grab the style information. Some of this will be duplicated so only insert 443 " it if it's not already there. {{{ 444 1 445 let style_start = search('^<style\( type="text/css"\)\?>') 446 1 447 let style_end = search('^</style>') 448 if style_start > 0 && style_end > 0 449 let buf_styles = getline(style_start + 1, style_end - 1) 450 for a_style in buf_styles 451 if index(style, a_style) == -1 452 if diff_style_start == 0 453 if a_style =~ '\<Diff\(Change\|Text\|Add\|Delete\)' 454 let diff_style_start = len(style)-1 455 endif 456 endif 457 call insert(style, a_style, insert_index) 458 let insert_index += 1 459 endif 460 endfor 461 endif " }}} 462 463 " everything new will get added before the diff styles so diff highlight 464 " properly overrides normal highlight 465 if diff_style_start != 0 466 let insert_index = diff_style_start 467 endif 468 469 " Delete those parts that are not needed so we can include the rest into the 470 " resulting table. 471 1,/^<body.*\%(\n<!--.*-->\_s\+.*id='oneCharWidth'.*\_s\+.*id='oneInputWidth'.*\_s\+.*id='oneEmWidth'\)\?\zs/d_ 472 $ 473 ?</body>?,$d_ 474 let temp = getline(1,'$') 475 " clean out id on the main content container because we already set it on 476 " the table 477 let temp[0] = substitute(temp[0], " id='vimCodeElement[^']*'", "", "") 478 " undo deletion of start and end part 479 " so we can later save the file as valid html 480 " TODO: restore using grabbed lines if undolevel is 1? 481 normal! 2u 482 if s:settings.use_css 483 call add(html, '<td><div>') 484 elseif s:settings.use_xhtml 485 call add(html, '<td nowrap="nowrap" valign="top"><div>') 486 else 487 call add(html, '<td nowrap valign="top"><div>') 488 endif 489 let html += temp 490 call add(html, '</div></td>') 491 492 " Close this buffer 493 " TODO: the comment above says we're going to allow saving the file 494 " later...but here we discard it? 495 quit! 496 endfor 497 498 let html[body_line_num] = body_line 499 500 call add(html, '</tr>') 501 call add(html, '</table>') 502 call add(html, s:body_end_line) 503 call add(html, '</html>') 504 505 " The generated HTML is admittedly ugly and takes a LONG time to fold. 506 " Make sure the user doesn't do syntax folding when loading a generated file, 507 " using a modeline. 508 call add(html, '<!-- vim: set foldmethod=manual : -->') 509 510 let i = 1 511 let name = "Diff" . (s:settings.use_xhtml ? ".xhtml" : ".html") 512 " Find an unused file name if current file name is already in use 513 while filereadable(name) 514 let name = substitute(name, '\d*\.x\?html$', '', '') . i . '.' . fnamemodify(copy(name), ":t:e") 515 let i += 1 516 endwhile 517 518 let s:ei_sav = &eventignore 519 set eventignore+=FileType 520 exe "topleft new " . name 521 let &eventignore=s:ei_sav 522 unlet s:ei_sav 523 524 setlocal modifiable 525 526 " just in case some user autocmd creates content in the new buffer, make sure 527 " it is empty before proceeding 528 %d 529 530 " set the fileencoding to match the charset we'll be using 531 let &l:fileencoding=s:settings.vim_encoding 532 533 " According to http://www.w3.org/TR/html4/charset.html#doc-char-set, the byte 534 " order mark is highly recommend on the web when using multibyte encodings. But, 535 " it is not a good idea to include it on UTF-8 files. Otherwise, let Vim 536 " determine when it is actually inserted. 537 if s:settings.vim_encoding == 'utf-8' 538 setlocal nobomb 539 else 540 setlocal bomb 541 endif 542 543 call append(0, html) 544 545 if len(style) > 0 546 1 547 let style_start = search('^</head>')-1 548 549 " add required javascript in reverse order so we can just call append again 550 " and again without adjusting {{{ 551 552 let s:uses_script = s:settings.dynamic_folds || s:settings.line_ids 553 554 " insert script closing tag if needed 555 if s:uses_script 556 call append(style_start, [ 557 \ '', 558 \ s:settings.use_xhtml ? '//]]>' : '-->', 559 \ "</script>" 560 \ ]) 561 endif 562 563 " insert javascript to get IDs from line numbers, and to open a fold before 564 " jumping to any lines contained therein 565 if s:settings.line_ids 566 call append(style_start, [ 567 \ " /* Always jump to new location even if the line was hidden inside a fold, or", 568 \ " * we corrected the raw number to a line ID.", 569 \ " */", 570 \ " if (lineElem) {", 571 \ " lineElem.scrollIntoView(true);", 572 \ " }", 573 \ " return true;", 574 \ "}", 575 \ "if ('onhashchange' in window) {", 576 \ " window.onhashchange = JumpToLine;", 577 \ "}" 578 \ ]) 579 580 if s:settings.dynamic_folds 581 call append(style_start, [ 582 \ "", 583 \ " /* navigate upwards in the DOM tree to open all folds containing the line */", 584 \ " var node = lineElem;", 585 \ " while (node && node.id != 'vimCodeElement".s:settings.id_suffix."')", 586 \ " {", 587 \ " if (node.className == 'closed-fold')", 588 \ " {", 589 \ " /* toggle open the fold ID (remove window ID) */", 590 \ " toggleFold(node.id.substr(4));", 591 \ " }", 592 \ " node = node.parentNode;", 593 \ " }", 594 \ ]) 595 endif 596 endif 597 598 if s:settings.line_ids 599 call append(style_start, [ 600 \ "", 601 \ "/* function to open any folds containing a jumped-to line before jumping to it */", 602 \ "function JumpToLine()", 603 \ "{", 604 \ " var lineNum;", 605 \ " lineNum = window.location.hash;", 606 \ " lineNum = lineNum.substr(1); /* strip off '#' */", 607 \ "", 608 \ " if (lineNum.indexOf('L') == -1) {", 609 \ " lineNum = 'L'+lineNum;", 610 \ " }", 611 \ " if (lineNum.indexOf('W') == -1) {", 612 \ " lineNum = 'W1'+lineNum;", 613 \ " }", 614 \ " var lineElem = document.getElementById(lineNum);" 615 \ ]) 616 endif 617 618 " Insert javascript to toggle matching folds open and closed in all windows, 619 " if dynamic folding is active. 620 if s:settings.dynamic_folds 621 call append(style_start, [ 622 \ " function toggleFold(objID)", 623 \ " {", 624 \ " for (win_num = 1; win_num <= ".len(a:buf_list)."; win_num++)", 625 \ " {", 626 \ " var fold;", 627 \ ' fold = document.getElementById("win"+win_num+objID);', 628 \ " if(fold.className == 'closed-fold')", 629 \ " {", 630 \ " fold.className = 'open-fold';", 631 \ " }", 632 \ " else if (fold.className == 'open-fold')", 633 \ " {", 634 \ " fold.className = 'closed-fold';", 635 \ " }", 636 \ " }", 637 \ " }", 638 \ ]) 639 endif 640 641 if s:uses_script 642 " insert script tag if needed 643 call append(style_start, [ 644 \ "<script" . (s:html5 ? "" : " type='text/javascript'") . ">", 645 \ s:settings.use_xhtml ? '//<![CDATA[' : "<!--"]) 646 endif 647 648 " Insert styles from all the generated html documents and additional styles 649 " for the table-based layout of the side-by-side diff. The diff should take 650 " up the full browser window (but not more), and be static in size, 651 " horizontally scrollable when the lines are too long. Otherwise, the diff 652 " is pretty useless for really long lines. {{{ 653 if s:settings.use_css 654 call append(style_start, 655 \ ['<style' . (s:html5 ? '' : 'type="text/css"') . '>']+ 656 \ style+ 657 \ [ s:settings.use_xhtml ? '' : '<!--', 658 \ 'table { table-layout: fixed; }', 659 \ 'html, body, table, tbody { width: 100%; margin: 0; padding: 0; }', 660 \ 'table, td, th { border: 1px solid; }', 661 \ 'td { vertical-align: top; }', 662 \ 'th, td { width: '.printf("%.1f",100.0/len(a:win_list)).'%; }', 663 \ 'td div { overflow: auto; }', 664 \ s:settings.use_xhtml ? '' : '-->', 665 \ '</style>' 666 \]) 667 endif "}}} 668 endif 669 670 let &paste = s:old_paste 671 let &magic = s:old_magic 672endfunc "}}} 673 674" Gets a single user option and sets it in the passed-in Dict, or gives it the 675" default value if the option doesn't actually exist. 676func! tohtml#GetOption(settings, option, default) "{{{ 677 if exists('g:html_'.a:option) 678 let a:settings[a:option] = g:html_{a:option} 679 else 680 let a:settings[a:option] = a:default 681 endif 682endfunc "}}} 683 684" returns a Dict containing the values of all user options for 2html, including 685" default values for those not given an explicit value by the user. Discards the 686" html_ prefix of the option for nicer looking code. 687func! tohtml#GetUserSettings() "{{{ 688 if exists('s:settings') 689 " just restore the known options if we've already retrieved them 690 return s:settings 691 else 692 " otherwise figure out which options are set 693 let user_settings = {} 694 695 " Define the correct option if the old option name exists and we haven't 696 " already defined the correct one. Maybe I'll put out a warning message about 697 " this sometime and remove the old option entirely at some even later time, 698 " but for now just silently accept the old option. 699 if exists('g:use_xhtml') && !exists("g:html_use_xhtml") 700 let g:html_use_xhtml = g:use_xhtml 701 endif 702 703 " get current option settings with appropriate defaults {{{ 704 call tohtml#GetOption(user_settings, 'no_progress', !has("statusline") ) 705 call tohtml#GetOption(user_settings, 'diff_one_file', 0 ) 706 call tohtml#GetOption(user_settings, 'number_lines', &number ) 707 call tohtml#GetOption(user_settings, 'pre_wrap', &wrap ) 708 call tohtml#GetOption(user_settings, 'use_css', 1 ) 709 call tohtml#GetOption(user_settings, 'ignore_conceal', 0 ) 710 call tohtml#GetOption(user_settings, 'ignore_folding', 0 ) 711 call tohtml#GetOption(user_settings, 'dynamic_folds', 0 ) 712 call tohtml#GetOption(user_settings, 'no_foldcolumn', user_settings.ignore_folding) 713 call tohtml#GetOption(user_settings, 'hover_unfold', 0 ) 714 call tohtml#GetOption(user_settings, 'no_pre', 0 ) 715 call tohtml#GetOption(user_settings, 'no_invalid', 0 ) 716 call tohtml#GetOption(user_settings, 'whole_filler', 0 ) 717 call tohtml#GetOption(user_settings, 'use_xhtml', 0 ) 718 call tohtml#GetOption(user_settings, 'line_ids', user_settings.number_lines ) 719 call tohtml#GetOption(user_settings, 'use_input_for_pc', 'fallback') 720 " }}} 721 722 " override those settings that need it {{{ 723 724 " hover opening implies dynamic folding 725 if user_settings.hover_unfold 726 let user_settings.dynamic_folds = 1 727 endif 728 729 " ignore folding overrides dynamic folding 730 if user_settings.ignore_folding && user_settings.dynamic_folds 731 let user_settings.dynamic_folds = 0 732 let user_settings.hover_unfold = 0 733 endif 734 735 " dynamic folding with no foldcolumn implies hover opens 736 if user_settings.dynamic_folds && user_settings.no_foldcolumn 737 let user_settings.hover_unfold = 1 738 endif 739 740 " dynamic folding implies css 741 if user_settings.dynamic_folds 742 let user_settings.use_css = 1 743 else 744 let user_settings.no_foldcolumn = 1 " won't do anything but for consistency and for the test suite 745 endif 746 747 " if we're not using CSS we cannot use a pre section because <font> tags 748 " aren't allowed inside a <pre> block 749 if !user_settings.use_css 750 let user_settings.no_pre = 1 751 endif 752 753 " pre_wrap doesn't do anything if not using pre or not using CSS 754 if user_settings.no_pre || !user_settings.use_css 755 let user_settings.pre_wrap=0 756 endif 757 "}}} 758 759 " set up expand_tabs option after all the overrides so we know the 760 " appropriate defaults {{{ 761 if user_settings.no_pre == 0 762 call tohtml#GetOption(user_settings, 763 \ 'expand_tabs', 764 \ &expandtab || &ts != 8 || &vts != '' || user_settings.number_lines || 765 \ (user_settings.dynamic_folds && !user_settings.no_foldcolumn)) 766 else 767 let user_settings.expand_tabs = 1 768 endif 769 " }}} 770 771 " textual options 772 if exists("g:html_use_encoding") "{{{ 773 " user specified the desired MIME charset, figure out proper 774 " 'fileencoding' from it or warn the user if we cannot 775 let user_settings.encoding = g:html_use_encoding 776 let user_settings.vim_encoding = tohtml#EncodingFromCharset(g:html_use_encoding) 777 if user_settings.vim_encoding == '' 778 echohl WarningMsg 779 echomsg "TOhtml: file encoding for" 780 \ g:html_use_encoding 781 \ "unknown, please set 'fileencoding'" 782 echohl None 783 endif 784 else 785 " Figure out proper MIME charset from 'fileencoding' if possible 786 if &l:fileencoding != '' 787 " If the buffer is not a "normal" type, the 'fileencoding' value may not 788 " be trusted; since the buffer should not be written the fileencoding is 789 " not intended to be used. 790 if &l:buftype=='' || &l:buftype==?'help' 791 let user_settings.vim_encoding = &l:fileencoding 792 call tohtml#CharsetFromEncoding(user_settings) 793 else 794 let user_settings.encoding = '' " trigger detection using &encoding 795 endif 796 endif 797 798 " else from 'encoding' if possible 799 if &l:fileencoding == '' || user_settings.encoding == '' 800 let user_settings.vim_encoding = &encoding 801 call tohtml#CharsetFromEncoding(user_settings) 802 endif 803 804 " else default to UTF-8 and warn user 805 if user_settings.encoding == '' 806 let user_settings.vim_encoding = 'utf-8' 807 let user_settings.encoding = 'UTF-8' 808 echohl WarningMsg 809 echomsg "TOhtml: couldn't determine MIME charset, using UTF-8" 810 echohl None 811 endif 812 endif "}}} 813 814 " Default to making nothing uncopyable, because we default to 815 " not-standards way of doing things, and also because Microsoft Word and 816 " others paste the <input> elements anyway. 817 " 818 " html_prevent_copy only has an effect when using CSS. 819 " 820 " All options: 821 " f - fold column 822 " n - line numbers (also within fold text) 823 " t - fold text 824 " d - diff filler 825 " c - concealed text (reserved future) 826 " l - listchars (reserved possible future) 827 " s - signs (reserved possible future) 828 " 829 " Normal text is always selectable. 830 let user_settings.prevent_copy = "" 831 if user_settings.use_css 832 if exists("g:html_prevent_copy") 833 if user_settings.dynamic_folds && !user_settings.no_foldcolumn && g:html_prevent_copy =~# 'f' 834 let user_settings.prevent_copy .= 'f' 835 endif 836 if user_settings.number_lines && g:html_prevent_copy =~# 'n' 837 let user_settings.prevent_copy .= 'n' 838 endif 839 if &diff && g:html_prevent_copy =~# 'd' 840 let user_settings.prevent_copy .= 'd' 841 endif 842 if !user_settings.ignore_folding && g:html_prevent_copy =~# 't' 843 let user_settings.prevent_copy .= 't' 844 endif 845 else 846 let user_settings.prevent_copy = "" 847 endif 848 endif 849 if empty(user_settings.prevent_copy) 850 let user_settings.no_invalid = 0 851 endif 852 853 " enforce valid values for use_input_for_pc 854 if user_settings.use_input_for_pc !~# 'fallback\|none\|all' 855 let user_settings.use_input_for_pc = 'fallback' 856 echohl WarningMsg 857 echomsg '2html: "' . g:html_use_input_for_pc . '" is not valid for g:html_use_input_for_pc' 858 echomsg '2html: defaulting to "' . user_settings.use_input_for_pc . '"' 859 echohl None 860 sleep 3 861 endif 862 863 if exists('g:html_id_expr') 864 let user_settings.id_suffix = eval(g:html_id_expr) 865 if user_settings.id_suffix !~ '^[-_:.A-Za-z0-9]*$' 866 echohl WarningMsg 867 echomsg '2html: g:html_id_expr evaluated to invalid string for HTML id attributes' 868 echomsg '2html: Omitting user-specified suffix' 869 echohl None 870 sleep 3 871 let user_settings.id_suffix="" 872 endif 873 else 874 let user_settings.id_suffix="" 875 endif 876 877 " TODO: font 878 879 return user_settings 880 endif 881endfunc "}}} 882 883" get the proper HTML charset name from a Vim encoding option. 884function! tohtml#CharsetFromEncoding(settings) "{{{ 885 let l:vim_encoding = a:settings.vim_encoding 886 if exists('g:html_charset_override') && has_key(g:html_charset_override, l:vim_encoding) 887 let a:settings.encoding = g:html_charset_override[l:vim_encoding] 888 else 889 if l:vim_encoding =~ '^8bit\|^2byte' 890 " 8bit- and 2byte- prefixes are to indicate encodings available on the 891 " system that Vim will convert with iconv(), look up just the encoding name, 892 " not Vim's prefix. 893 let l:vim_encoding = substitute(l:vim_encoding, '^8bit-\|^2byte-', '', '') 894 endif 895 if has_key(g:tohtml#encoding_to_charset, l:vim_encoding) 896 let a:settings.encoding = g:tohtml#encoding_to_charset[l:vim_encoding] 897 else 898 let a:settings.encoding = "" 899 endif 900 endif 901 if a:settings.encoding != "" 902 let l:vim_encoding = tohtml#EncodingFromCharset(a:settings.encoding) 903 if l:vim_encoding != "" 904 " if the Vim encoding to HTML encoding conversion is set up (by default or 905 " by the user) to convert to a different encoding, we need to also change 906 " the Vim encoding of the new buffer 907 let a:settings.vim_encoding = l:vim_encoding 908 endif 909 endif 910endfun "}}} 911 912" Get the proper Vim encoding option setting from an HTML charset name. 913function! tohtml#EncodingFromCharset(encoding) "{{{ 914 if exists('g:html_encoding_override') && has_key(g:html_encoding_override, a:encoding) 915 return g:html_encoding_override[a:encoding] 916 elseif has_key(g:tohtml#charset_to_encoding, tolower(a:encoding)) 917 return g:tohtml#charset_to_encoding[tolower(a:encoding)] 918 else 919 return "" 920 endif 921endfun "}}} 922 923let &cpo = s:cpo_sav 924unlet s:cpo_sav 925 926" Make sure any patches will probably use consistent indent 927" vim: ts=8 sw=2 sts=2 noet fdm=marker 928