cortav  Diff

Differences From Artifact [e8a2cf6308]:

To Artifact [214c9479d0]:


   136    136   		end;
   137    137   		[true] = function (job, ctx, words) 
   138    138   			local _, op, val = words(2)
   139    139   			if op == nil then
   140    140   				local toc = {kind='toc'}
   141    141   				ctx:insert(toc)
   142    142   				-- same deal here -- directives are processed as part of
   143         -				-- the parse job, which is forked off the document job,
   144         -				-- so we need to climb the jobstack
          143  +				-- the parse job, which is forked off the document job;
          144  +				-- if we want state that can persist into the render job,
          145  +            -- we need to climb the jobstack
   145    146   				job:unwind(1).state.toc_custom_position = true
   146    147   				job:hook('ext_toc_position', ctx, toc)
   147    148   			else
   148    149   				ctx:fail 'bad %toc directive'
   149    150   			end
   150    151   		end;
   151    152   	};
................................................................................
   188    189   				-- each node.
   189    190   				local stack = {lst}
   190    191   				local top = function() return stack[#stack] end
   191    192   				-- job.doc is the document the render job is bound to, and
   192    193   				-- its secorder field is a list of all the doc's sections in
   193    194   				-- the order they occur ("doc.sections" is a hashmap from name
   194    195   				-- to section object)
   195         -				local all = job.doc.secorder
          196  +				local all = {}
          197  +
          198  +				local function blockHasSubdoc(b)
          199  +					local subdocBlockKinds = {
          200  +						quote = true;
          201  +						embed = true;
          202  +						macro = true;
          203  +					}
          204  +					return subdocBlockKinds[b.kind] and ct.doc.is(b.doc)
          205  +				end
          206  +
          207  +            local function scandoc(doc, depth)
          208  +	            for i, sec in ipairs(doc.secorder) do
          209  +						table.insert(all, {ref = sec, depth = sec.depth + depth})
          210  +						for j, block in ipairs(sec.blocks) do
          211  +							if blockHasSubdoc(block) then
          212  +								scandoc(block.doc, depth + sec.depth-1)
          213  +							end
          214  +						end
          215  +	            end
          216  +            end
          217  +
          218  +				scandoc(job.doc,0)
   196    219   
   197         -				for i, sec in ipairs(all) do
          220  +				for i, secptr in ipairs(all) do
          221  +					local sec = secptr.ref
   198    222   					if sec.heading_node then -- does this section have a label?
   199    223   						local ent = tag('li',nil,
   200    224   							 catenate{tag('a', {href='#'..getSafeID(sec)},
   201    225   								sr.htmlSpan(sec.heading_node.spans, sec.heading_node, sec))})
   202         -						if sec.depth > #stack then
          226  +						if secptr.depth > #stack then
   203    227   							local n = {tag = 'ol', attrs={}, nodes={ent}}
   204    228   							table.insert(top().nodes[#top().nodes].nodes, n)
   205    229   							table.insert(stack, n)
   206    230   						else
   207         -							if sec.depth < #stack then
   208         -								for j=#stack,sec.depth+1,-1 do stack[j] = nil end
          231  +							if secptr.depth < #stack then
          232  +								for j=#stack,secptr.depth+1,-1 do stack[j] = nil end
   209    233   							end
   210    234   							table.insert(top().nodes, ent)
   211    235   						end
   212    236   
   213    237   						-- now we need to assemble a list of items within the
   214    238   						-- section worthy of an entry on their own. currently
   215    239   						-- this is only anchors created with %toc mark|name
................................................................................
   234    258   								local nn = {
   235    259   									tag = 'a';
   236    260   									attrs = {href = '#' .. l.id};
   237    261   									nodes = {sr.htmlSpan(l.label, l.block, sec)};
   238    262   								}
   239    263   								table.insert(n.nodes, {tag = 'li', attrs = {}, nodes={nn}})
   240    264   							end
   241         -							table.insert(ent.nodes, n)
          265  +							table.insert(top().nodes, n)
          266  +							table.insert(stack, n)
   242    267   						end
   243    268   					end
   244    269   				end
   245    270   				return lst
   246    271   			end;
   247    272   
   248    273   			[true] = function() end; -- fallback // convert to different node types
   249    274   		};
   250    275   	};
   251    276   }