Differences From
Artifact [78b49cf252]:
401 401 h1 {
402 402 page-break-before: always;
403 403 }
404 404 h1,h2,h3,h4,h5,h6 {
405 405 page-break-after: avoid;
406 406 }
407 407 ]];
408 + linkBlock = [[
409 + a[href].link {
410 + position: relative;
411 + display: block;
412 + padding: .5em;
413 + padding-right: 1.5em;
414 + border: 1px solid @tone(0.2 30);
415 + background: @tone(0.05 30);
416 + font-size: 1.1em;
417 + margin: 0 1em;
418 + text-decoration: none;
419 + color: @tone(0.8 30);
420 + }
421 + a[href].link + a[href].link {
422 + margin-top: -1px;
423 + }
424 + a[href].link:hover {
425 + border-color: @tone(0.3 30);
426 + background: @tone(0.2 30);
427 + color: @tone(0.95 30);
428 + }
429 + a[href].link:hover + a[href].link {
430 + margin-top: 0;
431 + border-top: none;
432 + }
433 + a[href].link::after {
434 + display: block;
435 + position: absolute;
436 + right: .5em;
437 + content: "→";
438 + top: 50%;
439 + margin-left: 1em;
440 + font-size: 1.8em;
441 + transform: translateY(-50%);
442 + color: @tone(0.3 30);
443 + }
444 + a[href].link:hover::after {
445 + color: @tone(0.7 30);
446 + }
447 + ]];
408 448 }
409 449
410 450 local stylesNeeded = {
411 451 flags = {};
412 452 order = {};
413 453 }
414 454 local function addStyle(sty)
................................................................................
447 487
448 488 local renderJob = doc:job('render_html', nil, render_state_handle)
449 489 doc.stage.job = renderJob;
450 490
451 491 local runhook = function(h, ...)
452 492 return renderJob:hook(h, render_state_handle, ...)
453 493 end
494 +
495 + local function htmlURI(uri)
496 + local family = uri:canfetch()
497 + if family == 'file' then
498 + if uri.namespace == 'localhost' then
499 + -- emit an actual file url
500 + return 'file://' .. uri:construct('path','frag')
501 + elseif uri.namespace == nil then
502 + -- this is gonna be tricky. first we establish the location
503 + -- of the CWD/asset base relative to the output file (if any;
504 + -- assume equivalent otherwise) then express the difference
505 + -- as a directory prefix.
506 + -- jk tho for now we just emit the path+frag sadlol TODO
507 + if uri.path == nil and uri.frag then
508 + -- file:#sec links to #sec within the current document
509 + return uri:part 'frag'
510 + else
511 + return uri:construct('path','frag')
512 + end
513 + else
514 + b.origin:fail('file: URI namespace must be empty or “localhost” for HTML links; others are not meaningful (offending URI: “%s”)', uri.raw)
515 + end
516 + elseif family == 'http' then
517 + local sc = 'http'
518 + if uri.class[1] == 'https' or uri.class[2] == 'tls' then
519 + sc = 'https'
520 + end
521 + if uri.namespace == nil and uri.auth == nil and uri.svc == nil then
522 + -- omit the scheme so we can use a relative path
523 + return uri:construct('path','query','frag')
524 + else
525 + uri.class = {sc}
526 + return tostring(uri)
527 + end
528 + else return tostring(uri) end
529 + end
530 +
531 + local function idLink(id,b)
532 + local dest_o, _, dest_s = b.origin:ref(id)
533 + if dest_o == nil then
534 + -- link is to the section itself
535 + return '#' .. getSafeID(dest_s)
536 + else
537 + if type(dest_o) == 'table' then
538 + return '#' .. getSafeID(dest_o)
539 + else -- URI in reference
540 + return htmlURI(ss.uri(dest_o))
541 + end
542 + end
543 + end
454 544
455 545 local tagproc do
456 546 local html_open = function(t,attrs)
457 547 if attrs then
458 548 return t .. ss.reduce(function(a,b) return a..b end, '',
459 549 ss.map(function(v,k)
460 550 if v == true
................................................................................
611 701 end
612 702
613 703 function span_renderers.raw(v,b,s)
614 704 return htmlSpan(v.spans, b, s)
615 705 end
616 706
617 707 function span_renderers.link(sp,b,s)
618 - local dest_o, _, dest_s = b.origin:ref(sp.ref)
619 - local href
620 - if dest_o == nil then
621 - -- link is to the section itself
622 - href = '#' .. getSafeID(dest_s)
623 - else
624 --- if sp.addr then href = sp.addr else
625 - if type(dest_o) == 'table' then
626 - href = '#' .. getSafeID(dest_o)
627 - else -- URI in reference
628 - local uri = ss.uri(dest_o)
629 - if uri.class[1] == 'file'
630 - or uri.class[1] == 'asset' then
631 - if uri.namespace == 'localhost' then
632 - -- emit an actual file url
633 - href = 'file://' .. uri:construct('path','frag')
634 - elseif uri.namespace == nil then
635 - -- this is gonna be tricky. first we establish the location
636 - -- of the CWD/asset base relative to the output file (if any;
637 - -- assume equivalent otherwise) then express the difference
638 - -- as a directory prefix.
639 - -- jk tho for now we just emit the path+frag sadlol TODO
640 - href = uri:construct('path','frag')
641 - else
642 - b.origin:fail('file: URI namespace must be empty or “localhost” for HTML links; others are not meaningful (offending URI: “%s”)', dest_o)
643 - end
644 - elseif uri:canfetch() == 'http' then
645 - local sc = 'http'
646 - if uri.class[1] == 'https' or uri.class[2] == 'tls' then
647 - sc = 'https'
648 - end
649 - if uri.namespace == nil and uri.auth == nil and uri.svc == nil then
650 - -- omit the scheme so we can use a relative path
651 - href = uri:construct('path','query','frag')
652 - else
653 - uri.class = {sc}
654 - href = tostring(uri)
655 - end
656 - else href = tostring(uri) end
657 - end
658 - end
659 - return tag('a',{href=href},next(sp.spans) and htmlSpan(sp.spans,b,s) or href)
708 + local href = idLink(sp.ref,b)
709 + return tag('a',{href=href}, next(sp.spans) and htmlSpan(sp.spans,b,s) or href)
660 710 end
661 711
662 712 span_renderers['line-break'] = function(sp,b,s)
663 713 return elt('br')
664 714 end
665 715
666 716 function span_renderers.macro(m,b,s)
................................................................................
773 823 else
774 824 -- handle other uses of labels here
775 825 end
776 826 end;
777 827 ['list-item'] = function(b,s)
778 828 return tag('li', nil, sr.htmlSpan(b.spans, b, s), b)
779 829 end;
830 + link = function(b,s)
831 + addStyle 'linkBlock'
832 + local href
833 + if b.uri then
834 + href = htmlURI(b.uri)
835 + elseif b.ref then
836 + href = idLink(b.ref, b)
837 + end
838 + local sp = sr.htmlSpan(b.spans, b, s)
839 + return tag('div', {},
840 + catenate{tag('a',{class='link', href=href},sp)})
841 + end;
780 842 table = function(b,s)
781 843 local tb = {}
782 844 for i, r in ipairs(b.rows) do
783 845 local row = {}
784 846 for i, c in ipairs(r) do
785 847 table.insert(row, tag(c.header and 'th' or 'td',
786 848 {align=c.align}, sr.htmlSpan(c.spans, b)))
................................................................................
863 925
864 926 function block_renderers.embed(b,s)
865 927 local obj
866 928 if b.rsrc
867 929 then obj = b.rsrc
868 930 else obj = b.origin:ref(b.ref)
869 931 end
870 - local function htmlURI(u)
871 - local family = u:canfetch()
872 - if family == 'file' or
873 - (family == 'http' and u.namespace == nil) then
874 - -- TODO asset:
875 - return u.path
876 - else
877 - return tostring(u)
878 - end
879 - end
880 932 local function uriForSource(s)
881 933 if s.mode == 'link' or s.mode == 'auto' then
882 934 return htmlURI(s.uri)
883 935 elseif s.mode == 'embed' then
884 936 local mime = s.mime:clone()
885 937 mime.opts = {}
886 938 return string.format('data:%s;base64,%s', mime, ss.str.b64e(s.raw))