cortav  Diff

Differences From Artifact [5903337619]:

To Artifact [9686e0dc58]:


   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