Support for absolute links when converting to HTML

Also, Fix #124
This commit is contained in:
EinfachToll 2015-04-09 14:48:26 +02:00
parent 62da755350
commit 99494655c2
4 changed files with 101 additions and 184 deletions

View File

@ -270,16 +270,20 @@ function! vimwiki#base#resolve_link(link_text, ...) "{{{
\ 'scheme': '',
\ 'filename': '',
\ 'anchor': '',
\ 'relative': 0,
\ }
" extract scheme
let link_infos.scheme = matchstr(link_text, g:vimwiki_rxSchemeUrlMatchScheme)
if !(link_infos.scheme =~# '\mwiki\d\+' || link_infos.scheme ==# 'diary' ||
\ link_infos.scheme ==# 'local' || link_infos.scheme ==# 'file')
if link_infos.scheme == '' || link_text == ''
let link_infos.filename = '' " malformed link
return link_infos
endif
if link_infos.scheme !~# '\mwiki\d\+\|diary\|local\|file'
let link_infos.filename = link_text " unknown scheme, may be a weblink
return link_infos
endif
let link_text = matchstr(link_text, g:vimwiki_rxSchemeUrlMatchUrl)
let is_wiki_link = link_infos.scheme =~# '\mwiki\d\+' ||
@ -300,12 +304,11 @@ function! vimwiki#base#resolve_link(link_text, ...) "{{{
" check if absolute or relative path
if is_wiki_link && link_text[0] == '/'
let link_text = link_text[1:]
let is_relative = 0
elseif !is_wiki_link && (link_text[0] == '/' ||
\ (link_text =~? '\m^\a:' && vimwiki#u#is_windows()))
let is_relative = 0
let link_infos.relative = 0
elseif !is_wiki_link && vimwiki#path#is_absolute(link_text)
let link_infos.relative = 0
else
let is_relative = 1
let link_infos.relative = 1
let root_dir = fnamemodify(source_file, ':p:h') . '/'
endif
@ -318,7 +321,7 @@ function! vimwiki#base#resolve_link(link_text, ...) "{{{
return link_infos
endif
if !is_relative || link_infos.index != source_wiki
if !link_infos.relative || link_infos.index != source_wiki
let root_dir = VimwikiGet('path', link_infos.index)
endif
@ -341,19 +344,15 @@ function! vimwiki#base#resolve_link(link_text, ...) "{{{
\ VimwikiGet('diary_rel_path', link_infos.index) .
\ link_text .
\ VimwikiGet('ext', link_infos.index)
elseif (link_infos.scheme ==# 'file' && is_relative) ||
\ link_infos.scheme ==# 'local'
let link_infos.filename = root_dir . link_text
elseif (link_infos.scheme ==# 'file' || link_infos.scheme ==# 'local')
\ && link_infos.relative
let link_infos.filename = simplify(root_dir . link_text)
else " absolute file link
" collapse repeated leading "/"'s within a link
let link_text = substitute(link_text, '\m^/*', '/', '')
" convert "/~..." into "~..." for fnamemodify
let link_text = substitute(link_text, '\m^/\~', '\~', '')
" convert /C: to C: (or fnamemodify(...":p:h") interpret it as C:\C:)
if vimwiki#u#is_windows()
let link_text = substitute(link_text, '\m^/\ze[[:alpha:]]:', '', '')
endif
let link_infos.filename = link_text
let link_text = substitute(link_text, '\m^/\+', '/', '')
" expand ~/
let link_text = fnamemodify(link_text, ':p')
let link_infos.filename = simplify(link_text)
endif
let link_infos.filename = vimwiki#path#normalize(link_infos.filename)
@ -361,146 +360,6 @@ function! vimwiki#base#resolve_link(link_text, ...) "{{{
endfunction "}}}
" vimwiki#base#resolve_scheme
function! vimwiki#base#resolve_scheme(lnk, as_html, ...) " {{{ Resolve scheme
let quiet = a:0 && a:1 ? 1 : 0
let lnk = a:lnk
" if link is schemeless add wikiN: scheme
let is_schemeless = lnk !~# g:vimwiki_rxSchemeUrl
let lnk = (is_schemeless ? 'wiki'.g:vimwiki_current_idx.':'.lnk : lnk)
" Get scheme
let scheme = matchstr(lnk, g:vimwiki_rxSchemeUrlMatchScheme)
" Get link (without scheme)
let lnk = matchstr(lnk, g:vimwiki_rxSchemeUrlMatchUrl)
let path = ''
let subdir = ''
let ext = ''
let idx = -1
let anchor = ''
"extract anchor
if scheme =~# 'wiki' || scheme =~# 'diary'
let split_lnk = split(lnk, '#', 1)
let lnk = split_lnk[0]
if len(split_lnk) <= 1 || split_lnk[-1] == ''
let anchor = ''
else
let anchor = join(split_lnk[1:], '#')
endif
endif
" do nothing if scheme is unknown to vimwiki
if !(scheme =~# 'wiki.*' || scheme =~# 'diary' || scheme =~# 'local'
\ || scheme =~# 'file')
return [idx, scheme, path, subdir, lnk, ext, scheme.':'.lnk, anchor]
endif
" scheme behaviors
if scheme =~# 'wiki\d\+'
let idx = eval(matchstr(scheme, '\D\+\zs\d\+\ze'))
if idx < 0 || idx >= len(g:vimwiki_list)
if !quiet
echom 'Vimwiki Error: Numbered scheme refers to a non-existent wiki!'
endif
return [idx,'','','','','','', '']
endif
if a:as_html
if idx == g:vimwiki_current_idx
let path = VimwikiGet('path_html')
else
let path = VimwikiGet('path_html', idx)
endif
else
if idx == g:vimwiki_current_idx
let path = VimwikiGet('path')
else
let path = VimwikiGet('path', idx)
endif
endif
" For Issue 310. Otherwise current subdir is used for another wiki.
if idx == g:vimwiki_current_idx
let subdir = VimwikiGet('subdir')
else
let subdir = ""
endif
if a:as_html
let ext = '.html'
else
if idx == g:vimwiki_current_idx
let ext = VimwikiGet('ext')
else
let ext = VimwikiGet('ext', idx)
endif
endif
" default link for directories
if vimwiki#path#is_link_to_dir(lnk)
let ext = (g:vimwiki_dir_link != '' ? g:vimwiki_dir_link . ext : '')
endif
elseif scheme =~# 'diary'
if a:as_html
" use cached value (save time when converting diary index!)
let path = VimwikiGet('invsubdir')
let ext = '.html'
else
let path = VimwikiGet('path')
let ext = VimwikiGet('ext')
endif
let idx = g:vimwiki_current_idx
let subdir = VimwikiGet('diary_rel_path')
elseif scheme =~# 'local'
" revisiting the 'lcd'-bug ...
let path = VimwikiGet('path')
let subdir = VimwikiGet('subdir')
if a:as_html
" prepend browser-specific file: scheme
let path = 'file://'.fnamemodify(path, ":p")
endif
elseif scheme =~# 'file'
" RM repeated leading "/"'s within a link
let lnk = substitute(lnk, '^/*', '/', '')
" convert "/~..." into "~..." for fnamemodify
let lnk = substitute(lnk, '^/\~', '\~', '')
" convert /C: to C: (or fnamemodify(...":p:h") interpret it as C:\C:
if vimwiki#u#is_windows()
let lnk = substitute(lnk, '^/\ze[[:alpha:]]:', '', '')
endif
if a:as_html
" prepend browser-specific file: scheme
let path = 'file://'.fnamemodify(lnk, ":p:h").'/'
else
let path = fnamemodify(lnk, ":p:h").'/'
endif
let lnk = fnamemodify(lnk, ":p:t")
let subdir = ''
endif
" construct url from parts
if is_schemeless && a:as_html
let scheme = ''
let url = lnk.ext
else
let url = path.subdir.lnk.ext
endif
" lnk and url should be '' if the given wiki link has the form [[#anchor]].
" We cannot do lnk = expand('%:t:r') or so, because this function is called
" from vimwiki#html#WikiAll2HTML() for many files, so expand('%:t:r')
" doesn't give the currently processed file
if lnk == ''
let url = ''
endif
" result
return [idx, scheme, path, subdir, lnk, ext, url, anchor]
endfunction "}}}
" vimwiki#base#system_open_link
function! vimwiki#base#system_open_link(url) "{{{
" handlers
@ -847,7 +706,8 @@ function! s:get_links(wikifile, idx) "{{{
endif
let link_count += 1
let target = vimwiki#base#resolve_link(link_text, a:wikifile)
if target.filename != ''
if target.filename != '' &&
\ target.scheme =~# '\mwiki\d\+\|diary\|file\|local'
call add(links, [target.filename, target.anchor, lnum, col])
endif
endwhile

View File

@ -372,19 +372,20 @@ function! s:tag_wikiincl(value) "{{{
let url_0 = matchstr(str, g:vimwiki_rxWikiInclMatchUrl)
let descr = matchstr(str, vimwiki#html#incl_match_arg(1))
let verbatim_str = matchstr(str, vimwiki#html#incl_match_arg(2))
" resolve url
let [idx, scheme, path, subdir, lnk, ext, url, anchor] =
\ vimwiki#base#resolve_scheme(url_0, 1, 1)
" generate html output
let link_infos = vimwiki#base#resolve_link(url_0)
" TODO: migrate non-essential debugging messages into g:VimwikiLog
if g:vimwiki_debug > 1
echom '{{idx='.idx.', scheme='.scheme.', path='.path.', subdir='.subdir.', lnk='.lnk.', ext='.ext.'}}'
echom string(link_infos)
endif
" Issue 343: Image transclusions: schemeless links have .html appended.
" If link is schemeless pass it as it is
if scheme == ''
let url = lnk
let url = 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
let url = escape(url, '#')
@ -406,20 +407,40 @@ function! s:tag_wikilink(value) "{{{
let descr = matchstr(str, g:vimwiki_rxWikiLinkMatchDescr)
let descr = (substitute(descr,'^\s*\(.*\)\s*$','\1','') != '' ? descr : url)
" resolve url
let [idx, scheme, path, subdir, lnk, ext, url, anchor] =
\ vimwiki#base#resolve_scheme(url, 1, 1)
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)
" generate html output
" TODO: migrate non-essential debugging messages into g:VimwikiLog
if g:vimwiki_debug > 1
echom '[[idx='.idx.', scheme='.scheme.', path='.path.', subdir='.subdir.', lnk='.lnk.', ext='.ext.']]'
if link_infos.scheme ==# 'file' || link_infos.scheme ==# 'local'
" external file links are always absolute
let html_link = link_infos.filename
else
" wiki links are always relative to the current file
echom link_infos.filename fnamemodify(s:current_wiki_file, ':h') fnamemodify(link_infos.filename, ':r')
let html_link = vimwiki#path#relpath(
\ fnamemodify(s:current_wiki_file, ':h'),
\ fnamemodify(link_infos.filename, ':r'))
echom html_link
if html_link !~ '\m/$'
let html_link .= '.html'
endif
endif
" generate html output
" TODO: migrate non-essential debugging messages into g:VimwikiLog
if g:vimwiki_debug > 1
echom string(link_infos)
endif
if link_infos.anchor != ''
let anchor = substitute(link_infos.anchor, '#', '-', 'g')
let html_link .= '#'.anchor
endif
let line = html_link
endif
if anchor != ''
let anchor = substitute(anchor, '#', '-', 'g')
let url .= '#'.anchor
endif
let line = vimwiki#html#linkify_link(url, descr)
let line =vimwiki#html#linkify_link(line, descr)
return line
endfunction "}}}
"}}}
@ -1338,6 +1359,11 @@ function! vimwiki#html#Wiki2HTML(path_html, wikifile) "{{{
let path_html = expand(a:path_html).VimwikiGet('subdir')
let htmlfile = fnamemodify(wikifile, ":t:r").'.html'
" the currently processed file name is needed when processing links
" yeah yeah, shame on me for using (quasi-) global variables
let s:current_wiki_file = wikifile
let s:current_html_file = path_html . htmlfile
if s:use_custom_wiki2html()
let force = 1
call vimwiki#html#CustomWiki2HTML(path_html, wikifile, force)

View File

@ -92,13 +92,20 @@ function! vimwiki#path#relpath(dir, file) "{{{
call remove(dir, 0)
call remove(file, 0)
endwhile
if empty(dir) && empty(file)
return './'
endif
for segment in dir
let result += ['..']
endfor
for segment in file
let result += [segment]
endfor
return join(result, '/')
let result_path = join(result, '/')
if a:file =~ '\m/$'
let result_path .= '/'
endif
return result_path
endfunction "}}}
" If the optional argument provided and nonzero,
@ -133,3 +140,11 @@ function! vimwiki#path#mkdir(path, ...) "{{{
return 1
endif
endfunction " }}}
function! vimwiki#path#is_absolute(path) "{{{
if vimwiki#u#is_windows()
return a:path =~? '\m^\a:'
else
return a:path =~# '\m^/\|\~/'
endif
endfunction "}}}

View File

@ -748,11 +748,27 @@ Link with spaces in it: >
or: >
[[This is a link source|Description of the link]]
Links to directories (ending with a "/") are also supported: >
[[/home/somebody/|Home Directory]]
Wiki files don't need to be in the root directory of your wiki, you can put
them in subdirectories as well: >
[[projects/Important Project 1]]
To jump from that file back to the index file, use this link: >
[[../index]]
or: >
[[/index]]
The latter works, because wiki links starting with "/" are considered to be
absolute to the wiki root directory, that is, the link [[/index]] always opens
the file /path/to/your/wiki/index.wiki, no matter in which subdirectory you
are currently in.
Links to directories (ending with a "/") are also supported: >
[[a subdirectory/|Other files]]
Use |g:vimwiki_dir_link| to control the behavior when opening directories.
Typing wikilinks can be simplified by using Vim's omni completion (see
|compl-omni|) like so: >
[[ind<C-X><C-O>
which opens up a popup menu with all the wiki files starting with "ind".
Raw URLs~
Raw URLs are also supported: >