Differences From
Artifact [5903337619]:
634 634 end
635 635
636 636 function span_renderers.macro(m,b,s)
637 637 local macroname = plainrdr.htmlSpan(
638 638 ct.parse_span(m.macro, b.origin), b,s)
639 639 local r = b.origin:ref(macroname)
640 640 if type(r) ~= 'string' then
641 - b.origin:fail('%s is an object, not a reference', t.ref)
641 + b.origin:fail('%s is an object, not a reference', r.id)
642 642 end
643 643 local mctx = b.origin:clone()
644 644 mctx.invocation = m
645 645 return htmlSpan(ct.parse_span(r, mctx),b,s)
646 646 end
647 647 function span_renderers.math(m,b,s)
648 648 addStyle 'math'
................................................................................
732 732 end
733 733 end;
734 734 label = function(b,s)
735 735 if ct.sec.is(b.captions) then
736 736 if not (opts['fossil-uv'] or opts.snippet) then
737 737 addStyle 'header'
738 738 end
739 - local h = math.min(6,math.max(1,b.captions.depth))
739 + -- use correct styling in subdocuments
740 + local visDepth = b.captions.depth + (b.origin.docDepth or 0)
741 + local h = math.min(6,math.max(1,visDepth))
740 742 return tag(f('h%u',h), nil, sr.htmlSpan(b.spans, b, s), b)
741 743 else
742 744 -- handle other uses of labels here
743 745 end
744 746 end;
745 747 ['list-item'] = function(b,s)
746 748 return tag('li', nil, sr.htmlSpan(b.spans, b, s), b)
................................................................................
786 788 end;
787 789 ['break'] = function() -- HACK
788 790 -- lists need to be rewritten to work like asides
789 791 return '';
790 792 end;
791 793 }
792 794
793 - function block_renderers.quote(b,s)
795 + local function renderSubdoc(doc)
794 796 local ir = {}
795 - local toIR = block_renderers
796 - for i, sec in ipairs(b.doc.secorder) do
797 + for i, sec in ipairs(doc.secorder) do
797 798 local secnodes = {}
798 799 for i, bl in ipairs(sec.blocks) do
799 - if toIR[bl.kind] then
800 - table.insert(secnodes, toIR[bl.kind](bl,sec))
800 + if block_renderers[bl.kind] then
801 + table.insert(secnodes, block_renderers[bl.kind](bl,sec))
801 802 end
802 803 end
803 804 if next(secnodes) then
804 - if b.doc.secorder[2] then --#secs>1?
805 + if doc.secorder[2] then --#secs>1?
805 806 -- only wrap in a section if >1 section
806 807 table.insert(ir, tag('section',
807 808 {id = getSafeID(sec)},
808 809 secnodes))
809 810 else
810 811 ir = secnodes
811 812 end
812 813 end
813 814 end
814 - return tag('blockquote', b.id and {id=getSafeID(b)} or {}, catenate(ir))
815 + return ir
816 + end
817 +
818 + local function flatten(t)
819 + if t == nil then
820 + return ''
821 + elseif type(t) == 'string' then
822 + return t
823 + elseif type(t) == 'table' then
824 + if t[1] then
825 + return catenate(ss.map(flatten, t))
826 + elseif t.tag then
827 + return tag(t.tag, t.attrs or {}, flatten(t.nodes))
828 + elseif t.elt then
829 + return tag(t.elt, t.attrs or {})
830 + end
831 + end
832 + end
833 +
834 + function block_renderers.embed(b,s)
835 + local obj
836 + if b.rsrc
837 + then obj = b.rsrc
838 + else obj = b.origin:ref(b.ref)
839 + end
840 + local function htmlURI(u)
841 + local family = u:canfetch()
842 + if family == 'file' or
843 + (family == 'http' and u.namespace == nil) then
844 + -- TODO asset:
845 + return u.path
846 + else
847 + return tostring(u)
848 + end
849 + end
850 + local function uriForSource(s)
851 + if s.mode == 'link' or s.mode == 'auto' then
852 + return htmlURI(s.uri)
853 + elseif s.mode == 'embed' then
854 + local mime = s.mime:clone()
855 + mime.opts = {}
856 + return string.format('data:%s;base64,%s', mime, ss.str.b64e(s.raw))
857 + end
858 + end
859 + --figure out how to embed the given object
860 + local embedActs = {
861 + {ss.mime'image/*', function(s,ctr)
862 + if s == nil then
863 + return {tag = "picture", nodes = {}}
864 + else
865 + local uri = uriForSource(s)
866 + local fbimg, idx
867 + if next(ctr.nodes) == nil then
868 + idx = 1
869 + fbimg = {
870 + elt = 'img'; --fallback
871 + attrs = {
872 + alt = '';
873 + src = uri;
874 + };
875 + }
876 + else idx = #ctr.nodes end
877 + table.insert(ctr.nodes, idx, {
878 + elt = 'source'; --fallback
879 + attrs = { srcset = uri; };
880 + })
881 + if fbimg then
882 + table.insert(ctr.nodes,fbimg)
883 + else
884 + -- fallback <img> should be lowest-prio image
885 + ctr.nodes[#ctr.nodes].attrs.src = uri;
886 + end
887 + end
888 + end};
889 + {ss.mime'text/x.cortav', function(s,ctr)
890 + if s == nil then
891 + return {}
892 + elseif next(ctr) == nil then
893 + if (s.mode == 'embed' or s.mode == 'auto') and s.doc then
894 + ctr.tag = 'div'; -- kinda hacky, maybe fix
895 + ctr.nodes = renderSubdoc(s.doc)
896 + elseif s.mode == 'link' then
897 + -- yeah this is not gonna work my dude
898 + ctr.elt = 'embed';
899 + ctr.attrs = {
900 + type = 'text/x.cortav';
901 + src = htmlURI(s.uri);
902 + }
903 + end
904 + end
905 + end};
906 + {ss.mime'text/html', function(s,ctr)
907 + if s == nil then
908 + return {}
909 + elseif next(ctr) == nil then
910 + if (s.mode == 'embed' or s.mode == 'auto') and s.raw then
911 + ctr.tag = 'div'
912 + ctr.nodes = s.raw
913 + elseif s.mode == 'link' then
914 + ctr.elt = 'embed';
915 + ctr.attrs = {
916 + type = 'text/html';
917 + src = htmlURI(s.uri);
918 + }
919 + end
920 + end
921 + end};
922 + {ss.mime'text/*', function(s,ctr)
923 + if s == nil then
924 + return {}
925 + elseif next(ctr) == nil then
926 + local mime = s.mime:clone()
927 + mime.opts={}
928 + if (s.mode == 'embed' or s.mode == 'auto') and s.raw then
929 + ctr.tag = 'pre';
930 + ctr.nodes = s.raw
931 + elseif s.mode == 'link' then
932 + ctr.elt = 'embed';
933 + ctr.attrs = {
934 + type = tostring(mime);
935 + src = htmlURI(s.uri);
936 + }
937 + end
938 + end
939 + end};
940 + }
941 +
942 + local rtype
943 + local fallback
944 + for n, src in ipairs(obj.srcs) do
945 + if fallback == nil and (src.mode == 'link' or src.mode == 'auto') then
946 + fallback = src
947 + end
948 +
949 + for i, ea in ipairs(embedActs) do
950 + if ea[1] < src.mime then -- fits!
951 + rtype = ea
952 + goto compatFound
953 + end
954 + end
955 + end
956 + -- nothing found; install fallback link
957 + if fallback then
958 + local lnk = htmlURI(fallback.uri)
959 + return tag('a', {href=lnk},
960 + tag('div',{class=xref},
961 + string.format("→ %s [%s]", b.cap or '', tostring(fallback.mime))))
962 + else
963 + addStyle 'docmeta'
964 + return tag('div',{class="render-warn"},
965 + 'could not embed object type ' .. tostring(obj.srcs.mime))
966 + end
967 +
968 + ::compatFound::
969 + local top = rtype[2]() -- create container
970 + for n, src in ipairs(obj.srcs) do
971 + if rtype[1] < src.mime then
972 + rtype[2](src, top)
973 + end
974 + end
975 + local ft = flatten(top)
976 + return ft
977 + end
978 +
979 + function block_renderers.macro(b,s)
980 + local all = renderSubdoc(b.doc)
981 + local cat = catenate(ss.map(flatten,all))
982 + return tag('div', {}, cat)
983 + end
984 +
985 + function block_renderers.quote(b,s)
986 + local ir = renderSubdoc(b.doc)
987 + return tag('blockquote', b.id and {id=getSafeID(b)} or {}, catenate(ss.map(flatten,ir)))
815 988 end
816 989
817 - return block_renderers;
990 + return block_renderers
818 991 end
819 992
820 993 local function getRenderers(procs)
821 994 local span_renderers = getSpanRenderers(procs)
822 995 local r = getBaseRenderers(procs,span_renderers)
823 996 r.block_renderers = getBlockRenderers(procs, r)
824 997 return r