" vim:tabstop=2:shiftwidth=2:expandtab:textwidth=99
" Vimwiki autoload plugin file
" Description: HTML export
" Home: https://github.com/vimwiki/vimwiki/
if exists('g:loaded_vimwiki_html_auto') || &compatible
finish
endif
let g:loaded_vimwiki_html_auto = 1
" FIXME: Magics: Why not use the current syntax highlight
" This is due to historical copy paste and lazyness of markdown user
" text: *strong*
" let s:default_syntax.rxBold = '\*[^*]\+\*'
let s:rxBold = '\%(^\|\s\|[[:punct:]]\)\@<='.
\'\*'.
\'\%([^*`[:space:]][^*`]*[^*`[:space:]]\|[^*`[:space:]]\)'.
\'\*'.
\'\%([[:punct:]]\|\s\|$\)\@='
" text: _emphasis_ or *emphasis*
let s:rxItalic = '\%(^\|\s\|[[:punct:]]\)\@<='.
\'_'.
\'\%([^_`[:space:]][^_`]*[^_`[:space:]]\|[^_`[:space:]]\)'.
\'_'.
\'\%([[:punct:]]\|\s\|$\)\@='
" text: $ equation_inline $
let s:rxEqIn = '\$[^$`]\+\$'
" text: `code`
let s:rxCode = '`[^`]\+`'
" text: ~~deleted text~~
let s:rxDelText = '\~\~[^~`]\+\~\~'
" text: ^superscript^
let s:rxSuperScript = '\^[^^`]\+\^'
" text: ,,subscript,,
let s:rxSubScript = ',,[^,`]\+,,'
function! s:root_path(subdir) abort
return repeat('../', len(split(a:subdir, '[/\\]')))
endfunction
function! s:syntax_supported() abort
return vimwiki#vars#get_wikilocal('syntax') ==? 'default'
endfunction
function! s:remove_blank_lines(lines) abort
while !empty(a:lines) && a:lines[-1] =~# '^\s*$'
call remove(a:lines, -1)
endwhile
endfunction
function! s:is_web_link(lnk) abort
if a:lnk =~# '^\%(https://\|http://\|www.\|ftp://\|file://\|mailto:\)'
return 1
endif
return 0
endfunction
function! s:is_img_link(lnk) abort
if tolower(a:lnk) =~# '\.\%(png\|jpg\|gif\|jpeg\)$'
return 1
endif
return 0
endfunction
function! s:has_abs_path(fname) abort
if a:fname =~# '\(^.:\)\|\(^/\)'
return 1
endif
return 0
endfunction
function! s:find_autoload_file(name) abort
for path in split(&runtimepath, ',')
let fname = path.'/autoload/vimwiki/'.a:name
if glob(fname) !=? ''
return fname
endif
endfor
return ''
endfunction
function! s:default_CSS_full_name(path) abort
let path = expand(a:path)
let css_full_name = path . vimwiki#vars#get_wikilocal('css_name')
return css_full_name
endfunction
function! s:create_default_CSS(path) abort
let css_full_name = s:default_CSS_full_name(a:path)
if glob(css_full_name) ==? ''
call vimwiki#path#mkdir(fnamemodify(css_full_name, ':p:h'))
let default_css = s:find_autoload_file('style.css')
if default_css !=? ''
let lines = readfile(default_css)
call writefile(lines, css_full_name)
return 1
endif
endif
return 0
endfunction
function! s:template_full_name(name) abort
if a:name ==? ''
let name = vimwiki#vars#get_wikilocal('template_default')
else
let name = a:name
endif
let fname = expand(vimwiki#vars#get_wikilocal('template_path').
\ name . vimwiki#vars#get_wikilocal('template_ext'))
if filereadable(fname)
return fname
else
return ''
endif
endfunction
function! s:get_html_template(template) abort
" TODO: refactor it!!!
let lines=[]
if a:template !=? ''
let template_name = s:template_full_name(a:template)
try
let lines = readfile(template_name)
return lines
catch /E484/
echomsg 'Vimwiki: HTML template '.template_name. ' does not exist!'
endtry
endif
let default_tpl = s:template_full_name('')
if default_tpl ==? ''
let default_tpl = s:find_autoload_file('default.tpl')
endif
let lines = readfile(default_tpl)
return lines
endfunction
function! s:safe_html_preformatted(line) abort
let line = substitute(a:line,'<','\<', 'g')
let line = substitute(line,'>','\>', 'g')
return line
endfunction
function! s:escape_html_attribute(string) abort
return substitute(a:string, '"', '\"', 'g')
endfunction
function! s:safe_html_line(line) abort
" escape & < > when producing HTML text
" s:lt_pattern, s:gt_pattern depend on g:vimwiki_valid_html_tags
" and are set in vimwiki#html#Wiki2HTML()
let line = substitute(a:line, '&', '\&', 'g')
let line = substitute(line,s:lt_pattern,'\<', 'g')
let line = substitute(line,s:gt_pattern,'\>', 'g')
return line
endfunction
function! s:delete_html_files(path) abort
let htmlfiles = split(glob(a:path.'**/*.html'), '\n')
for fname in htmlfiles
" ignore user html files, e.g. search.html,404.html
if stridx(vimwiki#vars#get_global('user_htmls'), fnamemodify(fname, ':t')) >= 0
continue
endif
" delete if there is no corresponding wiki file
let subdir = vimwiki#base#subdir(vimwiki#vars#get_wikilocal('path_html'), fname)
let wikifile = vimwiki#vars#get_wikilocal('path').subdir.
\fnamemodify(fname, ':t:r').vimwiki#vars#get_wikilocal('ext')
if filereadable(wikifile)
continue
endif
try
call delete(fname)
catch
echomsg 'Vimwiki Error: Cannot delete '.fname
endtry
endfor
endfunction
function! s:mid(value, cnt) abort
return strpart(a:value, a:cnt, len(a:value) - 2 * a:cnt)
endfunction
function! s:subst_func(line, regexp, func, ...) abort
" Substitute text found by regexp with result of
" func(matched) function.
let pos = 0
let lines = split(a:line, a:regexp, 1)
let res_line = ''
for line in lines
let res_line = res_line.line
let matched = matchstr(a:line, a:regexp, pos)
if matched !=? ''
if a:0
let res_line = res_line.{a:func}(matched, a:1)
else
let res_line = res_line.{a:func}(matched)
endif
endif
let pos = matchend(a:line, a:regexp, pos)
endfor
return res_line
endfunction
function! s:process_date(placeholders, default_date) abort
if !empty(a:placeholders)
for [placeholder, row, idx] in a:placeholders
let [type, param] = placeholder
if type ==# 'date' && !empty(param)
return param
endif
endfor
endif
return a:default_date
endfunction
function! s:process_title(placeholders, default_title) abort
if !empty(a:placeholders)
for [placeholder, row, idx] in a:placeholders
let [type, param] = placeholder
if type ==# 'title' && !empty(param)
return param
endif
endfor
endif
return a:default_title
endfunction
function! s:is_html_uptodate(wikifile) abort
let tpl_time = -1
let tpl_file = s:template_full_name('')
if tpl_file !=? ''
let tpl_time = getftime(tpl_file)
endif
let wikifile = fnamemodify(a:wikifile, ':p')
if vimwiki#vars#get_wikilocal('html_filename_parameterization')
let parameterized_wikiname = s:parameterized_wikiname(wikifile)
let htmlfile = expand(vimwiki#vars#get_wikilocal('path_html') .
\ vimwiki#vars#get_bufferlocal('subdir') . parameterized_wikiname)
else
let htmlfile = expand(vimwiki#vars#get_wikilocal('path_html') .
\ vimwiki#vars#get_bufferlocal('subdir') . fnamemodify(wikifile, ':t:r').'.html')
endif
if getftime(wikifile) <= getftime(htmlfile) && tpl_time <= getftime(htmlfile)
return 1
endif
return 0
endfunction
function! s:parameterized_wikiname(wikifile) abort
let initial = fnamemodify(a:wikifile, ':t:r')
let lower_sanitized = tolower(initial)
let substituted = substitute(lower_sanitized, '[^a-z0-9_-]\+','-', 'g')
let substituted = substitute(substituted, '\-\+','-', 'g')
let substituted = substitute(substituted, '^-', '', 'g')
let substituted = substitute(substituted, '-$', '', 'g')
return substitute(substituted, '\-\+','-', 'g') . '.html'
endfunction
function! s:html_insert_contents(html_lines, content) abort
let lines = []
for line in a:html_lines
if line =~# '%content%'
let parts = split(line, '%content%', 1)
if empty(parts)
call extend(lines, a:content)
else
for idx in range(len(parts))
call add(lines, parts[idx])
if idx < len(parts) - 1
call extend(lines, a:content)
endif
endfor
endif
else
call add(lines, line)
endif
endfor
return lines
endfunction
function! s:tag_eqin(value) abort
" mathJAX wants \( \) for inline maths
return '\('.s:mid(a:value, 1).'\)'
endfunction
function! s:tag_em(value) abort
return ''.s:mid(a:value, 1).''
endfunction
function! s:tag_strong(value, header_ids) abort
let text = s:mid(a:value, 1)
let id = s:escape_html_attribute(text)
let complete_id = ''
for l in range(6)
if a:header_ids[l][0] !=? ''
let complete_id .= a:header_ids[l][0].'-'
endif
endfor
if a:header_ids[5][0] ==? ''
let complete_id = complete_id[:-2]
endif
let complete_id .= '-'.id
return ''.text.''
endfunction
function! s:tag_tags(value, header_ids) abort
let complete_id = ''
for level in range(6)
if a:header_ids[level][0] !=? ''
let complete_id .= a:header_ids[level][0].'-'
endif
endfor
if a:header_ids[5][0] ==? ''
let complete_id = complete_id[:-2]
endif
let complete_id = s:escape_html_attribute(complete_id)
let result = []
for tag in split(a:value, ':')
let id = s:escape_html_attribute(tag)
call add(result, ''.tag.'')
endfor
return join(result)
endfunction
function! s:tag_todo(value) abort
return ''.a:value.''
endfunction
function! s:tag_strike(value) abort
return ''.s:mid(a:value, 2).''
endfunction
function! s:tag_super(value) abort
return ''.s:mid(a:value, 1).''
endfunction
function! s:tag_sub(value) abort
return ''.s:mid(a:value, 2).''
endfunction
function! s:tag_code(value) abort
let l:retstr = ' 0.5)
\ ? 'black' : 'white'
let l:retstr .=
\ " style='background-color:" . l:str .
\ ';color:' . l:fg_color . ";'"
endif
let l:retstr .= '>'.s:safe_html_preformatted(l:str).'
'
return l:retstr
endfunction
" match n-th ARG within {{URL[|ARG1|ARG2|...]}}
" *c,d,e),...
function! s:incl_match_arg(nn_index) abort
let rx = vimwiki#vars#get_global('rxWikiInclPrefix'). vimwiki#vars#get_global('rxWikiInclUrl')
let rx = rx . repeat(vimwiki#vars#get_global('rxWikiInclSeparator') .
\ vimwiki#vars#get_global('rxWikiInclArg'), a:nn_index-1)
if a:nn_index > 0
let rx = rx. vimwiki#vars#get_global('rxWikiInclSeparator'). '\zs' .
\ vimwiki#vars#get_global('rxWikiInclArg') . '\ze'
endif
let rx = rx . vimwiki#vars#get_global('rxWikiInclArgs') .
\ vimwiki#vars#get_global('rxWikiInclSuffix')
return rx
endfunction
function! s:linkify_link(src, descr) abort
let src_str = ' href="'.s:escape_html_attribute(a:src).'"'
let descr = vimwiki#u#trim(a:descr)
let descr = (descr ==? '' ? a:src : descr)
let descr_str = (descr =~# vimwiki#vars#get_global('rxWikiIncl')
\ ? s:tag_wikiincl(descr)
\ : descr)
return ''.descr_str.''
endfunction
function! s:linkify_image(src, descr, verbatim_str) abort
let src_str = ' src="'.a:src.'"'
let descr_str = (a:descr !=? '' ? ' alt="'.a:descr.'"' : '')
let verbatim_str = (a:verbatim_str !=? '' ? ' '.a:verbatim_str : '')
return ''
endfunction
function! s:tag_weblink(value) abort
" Weblink Template -> descr
let str = a:value
let url = matchstr(str, vimwiki#vars#get_syntaxlocal('rxWeblinkMatchUrl'))
let descr = matchstr(str, vimwiki#vars#get_syntaxlocal('rxWeblinkMatchDescr'))
let line = s:linkify_link(url, descr)
return line
endfunction
function! s:tag_wikiincl(value) abort
" {{imgurl|arg1|arg2}} -> ???
" {{imgurl}} ->
" {{imgurl|descr|style="A"}} ->
" {{imgurl|descr|class="B"}} ->
let str = a:value
" custom transclusions
let line = VimwikiWikiIncludeHandler(str)
" otherwise, assume image transclusion
if line ==? ''
let url_0 = matchstr(str, vimwiki#vars#get_global('rxWikiInclMatchUrl'))
let descr = matchstr(str, s:incl_match_arg(1))
let verbatim_str = matchstr(str, s:incl_match_arg(2))
let link_infos = vimwiki#base#resolve_link(url_0)
if link_infos.scheme =~# '\mlocal\|wiki\d\+\|diary'
let url = vimwiki#path#relpath(fnamemodify(s:current_html_file, ':h'), link_infos.filename)
" strip the .html extension when we have wiki links, so that the user can
" simply write {{image.png}} to include an image from the wiki directory
if link_infos.scheme =~# '\mwiki\d\+\|diary'
let url = fnamemodify(url, ':r')
endif
else
let url = link_infos.filename
endif
let url = escape(url, '#')
let line = s:linkify_image(url, descr, verbatim_str)
endif
return line
endfunction
function! s:tag_wikilink(value) abort
" [[url]] -> url
" [[url|descr]] -> descr
" [[url|{{...}}]] -> ...
" [[fileurl.ext|descr]] -> descr
" [[dirurl/|descr]] -> descr
" [[url#a1#a2]] -> url#a1#a2
" [[#a1#a2]] -> #a1#a2
let str = a:value
let url = matchstr(str, vimwiki#vars#get_syntaxlocal('rxWikiLinkMatchUrl'))
let descr = matchstr(str, vimwiki#vars#get_syntaxlocal('rxWikiLinkMatchDescr'))
let descr = vimwiki#u#trim(descr)
let descr = (descr !=? '' ? descr : url)
let line = VimwikiLinkConverter(url, s:current_wiki_file, s:current_html_file)
if line ==? ''
let link_infos = vimwiki#base#resolve_link(url, s:current_wiki_file)
if link_infos.scheme ==# 'file'
" external file links are always absolute
let html_link = link_infos.filename
elseif link_infos.scheme ==# 'local'
let html_link = vimwiki#path#relpath(fnamemodify(s:current_html_file, ':h'),
\ link_infos.filename)
elseif link_infos.scheme =~# '\mwiki\d\+\|diary'
" wiki links are always relative to the current file
let html_link = vimwiki#path#relpath(
\ fnamemodify(s:current_wiki_file, ':h'),
\ fnamemodify(link_infos.filename, ':r'))
if html_link !~? '\m/$'
let html_link .= '.html'
endif
else " other schemes, like http, are left untouched
let html_link = link_infos.filename
endif
if link_infos.anchor !=? ''
let anchor = substitute(link_infos.anchor, '#', '-', 'g')
let html_link .= '#'.anchor
endif
let line = html_link
endif
let line = s:linkify_link(line, descr)
return line
endfunction
function! s:tag_remove_internal_link(value) abort
let value = s:mid(a:value, 2)
let line = ''
if value =~# '|'
let link_parts = split(value, '|', 1)
else
let link_parts = split(value, '][', 1)
endif
if len(link_parts) > 1
if len(link_parts) < 3
let style = ''
else
let style = link_parts[2]
endif
let line = link_parts[1]
else
let line = value
endif
return line
endfunction
function! s:tag_remove_external_link(value) abort
let value = s:mid(a:value, 1)
let line = ''
if s:is_web_link(value)
let lnkElements = split(value)
let head = lnkElements[0]
let rest = join(lnkElements[1:])
if rest ==? ''
let rest = head
endif
let line = rest
elseif s:is_img_link(value)
let line = '
'
else
" [alskfj sfsf] shouldn't be a link. So return it as it was --
" enclosed in [...]
let line = '['.value.']'
endif
return line
endfunction
function! s:make_tag(line, regexp, func, ...) abort
" Make tags for a given matched regexp.
" Exclude preformatted text and href links.
" FIXME
let patt_splitter = '\(`[^`]\+`\)\|'.
\ '\('.vimwiki#vars#get_syntaxlocal('rxPreStart').'.\+'.
\ vimwiki#vars#get_syntaxlocal('rxPreEnd').'\)\|'.
\ '\(\)\|'.
\ '\(
\)\|'.
\ '\(
') else call add(lines, '') endif let pre = [1, len(matchstr(a:line, '^\s*\ze{{{'))] let processed = 1 elseif pre[0] && a:line =~# '^\s*}}}\s*$' let pre = [0, 0] call add(lines, '') let processed = 1 elseif pre[0] let processed = 1 "XXX destroys indent in general! "call add(lines, substitute(a:line, '^\s\{'.pre[1].'}', '', '')) call add(lines, s:safe_html_preformatted(a:line)) endif return [processed, lines, pre] endfunction function! s:process_tag_math(line, math) abort " math is the list of [is_in_math, indent_of_math] let lines = [] let math = a:math let processed = 0 if !math[0] && a:line =~# '^\s*{{\$[^\(}}$\)]*\s*$' let class = matchstr(a:line, '{{$\zs.*$') "FIXME class cannot be any string! let class = substitute(class, '\s\+$', '', 'g') " store the environment name in a global variable in order to close the " environment properly let s:current_math_env = matchstr(class, '^%\zs\S\+\ze%') if s:current_math_env !=? '' call add(lines, substitute(class, '^%\(\S\+\)%', '\\begin{\1}', '')) elseif class !=? '' call add(lines, "\\\[".class) else call add(lines, "\\\[") endif let math = [1, len(matchstr(a:line, '^\s*\ze{{\$'))] let processed = 1 elseif math[0] && a:line =~# '^\s*}}\$\s*$' let math = [0, 0] if s:current_math_env !=? '' call add(lines, "\\end{".s:current_math_env.'}') else call add(lines, "\\\]") endif let processed = 1 elseif math[0] let processed = 1 call add(lines, substitute(a:line, '^\s\{'.math[1].'}', '', '')) endif return [processed, lines, math] endfunction function! s:process_tag_quote(line, quote) abort let lines = [] let quote = a:quote let processed = 0 if a:line =~# '^\s\{4,}\S' if !quote call add(lines, '') let quote = 1 endif let processed = 1 call add(lines, substitute(a:line, '^\s*', '', '')) elseif quote call add(lines, '') let quote = 0 endif return [processed, lines, quote] endfunction function! s:process_tag_arrow_quote(line, arrow_quote) abort let lines = [] let arrow_quote = a:arrow_quote let processed = 0 if a:line =~# '^\s*>' if !arrow_quote call add(lines, '') call add(lines, '') let arrow_quote = 0 endif return [processed, lines, arrow_quote] endfunction function! s:process_tag_list(line, lists) abort function! s:add_checkbox(line, rx_list) abort let st_tag = '') let arrow_quote = 1 endif let processed = 1 let stripped_line = substitute(a:line, '^\s*>\s*', '', '') if stripped_line =~# '^\s*$' call add(lines, '
') call add(lines, '') endif call add(lines, stripped_line) elseif arrow_quote call add(lines, '
') call add(lines, '
')
let para = 1
endif
let processed = 1
if vimwiki#vars#get_wikilocal('text_ignore_newline')
call add(lines, a:line)
else
call add(lines, a:line.'
')
endif
elseif para && a:line =~# '^\s*$'
call add(lines, '