@@ -614,17 +614,47 @@ return htmlSpan(v.spans, b, s) end function span_renderers.link(sp,b,s) + local dest_o, _, dest_s = b.origin:ref(sp.ref) local href - if b.origin.doc.sections[sp.ref] then - href = '#' .. getSafeID(sp) + if dest_o == nil then + -- link is to the section itself + href = '#' .. getSafeID(dest_s) else - if sp.addr then href = sp.addr else - local r = b.origin:ref(sp.ref) - if type(r) == 'table' then - href = '#' .. getSafeID(r) - else href = r end +-- if sp.addr then href = sp.addr else + if type(dest_o) == 'table' then + href = '#' .. getSafeID(dest_o) + else -- URI in reference + local uri = ss.uri(dest_o) + if uri.class[1] == 'file' + or uri.class[1] == 'asset' then + if uri.namespace == 'localhost' then + -- emit an actual file url + href = 'file://' .. uri:construct('path','frag') + elseif uri.namespace == nil then + -- this is gonna be tricky. first we establish the location + -- of the CWD/asset base relative to the output file (if any; + -- assume equivalent otherwise) then express the difference + -- as a directory prefix. + -- jk tho for now we just emit the path+frag sadlol TODO + href = uri:construct('path','frag') + else + b.origin:fail('file: URI namespace must be empty or “localhost” for HTML links; others are not meaningful (offending URI: “%s”)', dest_o) + end + elseif uri:canfetch() == 'http' then + local sc = 'http' + if uri.class[1] == 'https' or uri.class[2] == 'tls' then + sc = 'https' + end + if uri.namespace == nil and uri.auth == nil and uri.svc == nil then + -- omit the scheme so we can use a relative path + href = uri:construct('path','query','frag') + else + uri.class = {sc} + href = tostring(uri) + end + else href = tostring(uri) end end end return tag('a',{href=href},next(sp.spans) and htmlSpan(sp.spans,b,s) or href) end