cortav  Diff

Differences From Artifact [62c90e9915]:

To Artifact [3a20caca9a]:


19
20
21
22
23
24
25
26



27


28
29



30
31
32
33
34
35
36
...
140
141
142
143
144
145
146

147
148

149
150
151
152
153
154
155
...
400
401
402
403
404
405
406

407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
















































431
432
433
434
435
436
437
...
556
557
558
559
560
561
562


563
564
565
566


567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588



589
590
591
592
593
594
595
...
613
614
615
616
617
618
619
620


621
local lines = function(...)
	local s = ss.strac()
	for _, v in pairs{...} do s(v) end
	return s
end

local function gsan(str)
	local tocodepoint = function(ch)



		return string.format('\\[u%04X]', utf8.codepoint(ch))


	end
	str = str:gsub('(["\'\\])',tocodepoint)



	return str
end

local gtxt = ss.declare {
	ident = 'groff-text';
	mk = function() return {
		lines = {};
................................................................................
				spans = self.spans;
			}
		end;
		blocks = {};
		prop = {};
		block = function(self)
			local sub = self:clone()

			sub.spans = {}
			sub.blocks = nil

			sub.span = function(me, ln)
				local p = ss.clone(me.prop)
				p.txt = ln
				p.block = sub
				p.origin = me.origin
				table.insert(me.spans, p)
				return p
................................................................................
	local blockRenderers = {}
	blockRenderers['horiz-rule'] = function(rc, b, sec)
		rc.prop.margin = { top = 0.3 }
		rc.prop.underline = 0.1
	end
	function	blockRenderers.label(rc, b, sec)
		if ct.sec.is(b.captions) then

			local sizes = {36,24,12,8,4,2}
			local margins = {0,3}
			local dedents = {2.5,1.3,0.8,0.4}
			local uls = {3,1.5,0.5,0.25}
			rc.prop.dsz = sizes[b.captions.depth] or 10
			rc.prop.underline = uls[b.captions.depth]
			rc.prop.bold = b.captions.depth > 3
			rc.prop.margin = {
				top = margins[b.captions.depth] or 1;
				bottom = 0.1;
			}
			rc.prop.vassure = rc.prop.dsz+70;
			rc.prop.indent = -(dedents[b.captions.depth] or 0)
			rc.prop.chtitle = collectText(rc, b.spans, b.spec):compile()
			if b.captions.depth == 1 then
				rc.prop.breakBefore = true
			end
			rs.renderSpans(rc, b.spans, b, sec)
		else
			ss.bug 'tried to render label for an unknown object type':throw()
		end
	end
	function	blockRenderers.paragraph(rc, b, sec)
		rs.renderSpans(rc, b.spans, b, sec)
















































	end
	function rs.renderBlock(rc, b, sec, outerBlockRenderContext)
		if blockRenderers[b.kind] then
			local rcc = rc:block()
			blockRenderers[b.kind](rcc, b, sec)
		end
	end
................................................................................
			if ln.dsz then
				defer:req('ps +' .. tostring(0 - ln.dsz) .. 'p')
			else
				defer:req'ps'
			end
		end



		for i,s in pairs(b.spans) do
			rs.emitSpan(gtxt, s)
		end




		if ln.margin then
			if ln.margin.bottom then
				gtxt:req(string.format('sp %sm', ln.margin.bottom))
			end
		end

		defer:flush()

		if not ln.margin then gtxt:brk() end
	end

	local ir = {}
	for i, sec in ipairs(doc.secorder) do
		if sec.kind == 'ordinary' then
			local rc = mkrc()
			for j, b in ipairs(sec.blocks) do
				rs.renderBlock(rc, b, sec)
			end
			table.insert(ir, {blocks = rc.blocks, src = sec})
		end
	end




	local gd = gtxt()
	for i, s in ipairs(ir) do
		for j, b in ipairs(s.blocks) do
			rs.emitBlock(gd,b)
		end
	end
................................................................................
				top = s.depth
				doctitle = collectText(mkrc():block(), s.heading_node.spans, s.heading_node, s):compile()
			end
		end
	end
	macs('.ds doctitle '..doctitle)

	return macs:compile'\n' .. '\n' .. gd:compile()


end







|
>
>
>
|
>
>
|
<
>
>
>







 







>


>







 







>




|
|
|

|



|

|









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
|
|
|
<
>
>












|
|
|
|
|
|
|
|
|
|
>
>
>







 







|
>
>

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

34
35
36
37
38
39
40
41
42
43
...
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
...
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
...
614
615
616
617
618
619
620
621
622
623
624
625

626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
...
677
678
679
680
681
682
683
684
685
686
687
local lines = function(...)
	local s = ss.strac()
	for _, v in pairs{...} do s(v) end
	return s
end

local function gsan(str)
	-- groff does not support UTF-8
	local ascii = {}
	for p,c in utf8.codes(str) do
		if c > 0x7F or c == 0x27 or c == 0x22 or c == 0x5C then
			table.insert(ascii, string.format('\\[u%04X]', c))
		else
			table.insert(ascii, utf8.char(c))
		end

	end
	str = table.concat(ascii)
	str = str:gsub('\t','\\t') -- tabs are sometimes syntactically meaningful
	return str
end

local gtxt = ss.declare {
	ident = 'groff-text';
	mk = function() return {
		lines = {};
................................................................................
				spans = self.spans;
			}
		end;
		blocks = {};
		prop = {};
		block = function(self)
			local sub = self:clone()
			sub.parent = self -- needed for blocks that contain blocks
			sub.spans = {}
			sub.blocks = nil
			sub.block = nil
			sub.span = function(me, ln)
				local p = ss.clone(me.prop)
				p.txt = ln
				p.block = sub
				p.origin = me.origin
				table.insert(me.spans, p)
				return p
................................................................................
	local blockRenderers = {}
	blockRenderers['horiz-rule'] = function(rc, b, sec)
		rc.prop.margin = { top = 0.3 }
		rc.prop.underline = 0.1
	end
	function	blockRenderers.label(rc, b, sec)
		if ct.sec.is(b.captions) then
			local visDepth = b.captions.depth + (b.origin.docDepth or 0)
			local sizes = {36,24,12,8,4,2}
			local margins = {0,3}
			local dedents = {2.5,1.3,0.8,0.4}
			local uls = {3,1.5,0.5,0.25}
			rc.prop.dsz = sizes[visDepth] or 10
			rc.prop.underline = uls[visDepth]
			rc.prop.bold = visDepth > 3
			rc.prop.margin = {
				top = margins[visDepth] or 1;
				bottom = 0.1;
			}
			rc.prop.vassure = rc.prop.dsz+70;
			rc.prop.indent = -(dedents[visDepth] or 0)
			rc.prop.chtitle = collectText(rc, b.spans, b.spec):compile()
			if visDepth == 1 then
				rc.prop.breakBefore = true
			end
			rs.renderSpans(rc, b.spans, b, sec)
		else
			ss.bug 'tried to render label for an unknown object type':throw()
		end
	end
	function	blockRenderers.paragraph(rc, b, sec)
		rs.renderSpans(rc, b.spans, b, sec)
	end
	function	blockRenderers.macro(rc, b, sec)
		local rc = rc.parent:clone()
		rs.renderDoc(rc, b.doc)
	end
	function	blockRenderers.quote(rc, b, sec)
		local rc = rc.parent:clone()
		rc.prop.indent = (rc.prop.indent or 0) + 1
		local added = rs.renderDoc(rc, b.doc)
		 -- select last block of last section and increase bottom margin
		local ap = added[#added].blocks
		ap = ap[#ap].prop
		if ap.margin then
			if ap.margin.bottom then
				ap.margin.bottom = ap.margin.bottom + 1.1
			else
				ap.margin.bottom = 1.1
			end
		else
			ap.margin = {bottom = 1.1}
		end
	end
	function	blockRenderers.table(rc, b, sec)
		function rc:begin(g)
			g:req 'TS'
			local aligns = {}
			for i, c in ipairs(b.rows[1]) do
				aligns[i] = ({
					left = 'l';
					center = 'c';
					right = 'r';
				})[c.align] or 'l'
			end
			table.insert(aligns, '.')
			g:txt(table.concat(aligns, ' ') .. '\n')

			local rc_hdr = rc:clone()
			rc_hdr.prop.bold = true
			for ri, r in ipairs(b.rows) do
				for ci, c in ipairs(r) do
					local sp = collect(c.header and rc_hdr or rc, c.spans, b, sec)
					for si, s in ipairs(sp) do rs.emitSpan(g,s) end
					g:raw '\t'
				end
				if ri ~= #b.rows then g:raw '\n' end
			end
			g:req 'TE'
		end
	end
	function rs.renderBlock(rc, b, sec, outerBlockRenderContext)
		if blockRenderers[b.kind] then
			local rcc = rc:block()
			blockRenderers[b.kind](rcc, b, sec)
		end
	end
................................................................................
			if ln.dsz then
				defer:req('ps +' .. tostring(0 - ln.dsz) .. 'p')
			else
				defer:req'ps'
			end
		end

		if b.begin then b:begin(gtxt) end
		if b.spans then
			for i,s in pairs(b.spans) do
				rs.emitSpan(gtxt, s)
			end

		end
		if b.complete then b:complete(gtxt) end

		if ln.margin then
			if ln.margin.bottom then
				gtxt:req(string.format('sp %sm', ln.margin.bottom))
			end
		end

		defer:flush()

		if not ln.margin then gtxt:brk() end
	end

	function rs.renderDoc(gctx, doc, ir) ir = ir or {}
		for i, sec in ipairs(doc.secorder) do
			if sec.kind == 'ordinary' then
				local rc = gctx and gctx:clone() or mkrc()
				for j, b in ipairs(sec.blocks) do
					rs.renderBlock(rc, b, sec)
				end
				table.insert(ir, {blocks = rc.blocks, src = sec})
			end
		end
		return ir
	end
	local ir = rs.renderDoc(nil, doc)

	local gd = gtxt()
	for i, s in ipairs(ir) do
		for j, b in ipairs(s.blocks) do
			rs.emitBlock(gd,b)
		end
	end
................................................................................
				top = s.depth
				doctitle = collectText(mkrc():block(), s.heading_node.spans, s.heading_node, s):compile()
			end
		end
	end
	macs('.ds doctitle '..doctitle)

	return macs:compile'\n' .. '\n' .. gd:compile() .. '\n'
	-- if the document doesn't end with the character \n, groff will bitch
	-- and moan in certain circumstances
end