• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

sile-typesetter / sile / 14684598788

26 Apr 2025 07:55PM UTC coverage: 29.023% (-36.3%) from 65.328%
14684598788

push

github

alerque
test(fonts): Update test to work on new ICU instead of old

5840 of 20122 relevant lines covered (29.02%)

379.34 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

39.83
/packages/tableofcontents/init.lua
1
local base = require("packages.base")
2✔
2

3
local package = pl.class(base)
2✔
4
package._name = "tableofcontents"
2✔
5

6
if not SILE.scratch._tableofcontents then
2✔
7
   SILE.scratch._tableofcontents = {}
2✔
8
end
9

10
local toc_used = false
2✔
11

12
function package:moveTocNodes ()
2✔
13
   local node = SILE.scratch.info.thispage.toc
17✔
14
   if node then
17✔
15
      for i = 1, #node do
×
16
         node[i].pageno = self.packages.counters:formatCounter(SILE.scratch.counters.folio)
×
17
         table.insert(SILE.scratch.tableofcontents, node[i])
×
18
      end
19
   end
20
end
21

22
function package:writeToc ()
2✔
23
   local tocdata = pl.pretty.write(SILE.scratch.tableofcontents)
4✔
24
   local tocfile, err = io.open(pl.path.splitext(SILE.input.filenames[1]) .. ".toc", "w")
4✔
25
   if not tocfile then
2✔
26
      return SU.error(err)
×
27
   end
28
   tocfile:write("return " .. tocdata)
2✔
29
   tocfile:close()
2✔
30

31
   if toc_used and not pl.tablex.deepcompare(SILE.scratch.tableofcontents, SILE.scratch._tableofcontents) then
2✔
32
      SU.msg("Notice: the table of contents has changed, please rerun SILE to update it.")
×
33
   end
34
end
35

36
function package:readToc ()
2✔
37
   if SILE.scratch._tableofcontents and #SILE.scratch._tableofcontents > 0 then
×
38
      -- already loaded
39
      return SILE.scratch._tableofcontents
×
40
   end
41
   local tocfile_name = (pl.path.splitext(SILE.input.filenames[1]) .. ".toc")
×
42
   local tocfile, _ = io.open(tocfile_name)
×
43
   if not tocfile then
×
44
      return false -- No TOC yet
×
45
   end
46
   local doc = tocfile:read("*all")
×
47
   local toc = assert(load(doc), tocfile_name, "r")()
×
48
   SILE.scratch._tableofcontents = toc
×
49
   return SILE.scratch._tableofcontents
×
50
end
51

52
local function _linkWrapper (dest, func)
53
   if dest and SILE.Commands["pdf:link"] then
×
54
      return function ()
55
         SILE.call("pdf:link", { dest = dest }, func)
×
56
      end
57
   else
58
      return func
×
59
   end
60
end
61

62
if not SILE.scratch.pdf_destination_counter then
2✔
63
   SILE.scratch.pdf_destination_counter = 1
2✔
64
end
65

66
function package:_init ()
2✔
67
   base._init(self)
2✔
68
   if not SILE.scratch.tableofcontents then
2✔
69
      SILE.scratch.tableofcontents = {}
2✔
70
   end
71
   self:loadPackage("infonode")
2✔
72
   self:loadPackage("leaders")
2✔
73
   self.class:registerHook("endpage", self.moveTocNodes)
2✔
74
   self.class:registerHook("finish", self.writeToc)
2✔
75
   self:deprecatedExport("writeToc", self.writeToc)
2✔
76
   self:deprecatedExport("moveTocNodes", self.moveTocNodes)
2✔
77
end
78

79
function package:registerCommands ()
2✔
80
   self:registerCommand("tableofcontents", function (options, _)
4✔
81
      local depth = SU.cast("integer", options.depth or 3)
×
82
      local linking = SU.boolean(options.linking, true)
×
83
      toc_used = true
×
84
      local toc = self:readToc()
×
85
      if toc == false then
×
86
         SILE.call("tableofcontents:notocmessage")
×
87
         return
×
88
      end
89
      SILE.call("tableofcontents:header")
×
90
      for i = 1, #toc do
×
91
         local item = toc[i]
×
92
         if item.level <= depth then
×
93
            SILE.call("tableofcontents:item", {
×
94
               level = item.level,
95
               pageno = item.pageno,
96
               number = item.number,
97
               link = linking and item.link,
98
            }, item.label)
×
99
         end
100
      end
101
      SILE.call("tableofcontents:footer")
×
102
   end)
103

104
   self:registerCommand("tableofcontents:item", function (options, content)
4✔
105
      SILE.settings:temporarily(function ()
×
106
         SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue())
×
107
         SILE.call(
×
108
            "tableofcontents:level" .. options.level .. "item",
×
109
            {},
110
            _linkWrapper(options.link, function ()
×
111
               SILE.call("tableofcontents:level" .. options.level .. "number", {}, function ()
×
112
                  if options.number then
×
113
                     SILE.typesetter:typeset(options.number or "")
×
114
                     SILE.call("kern", { width = "1spc" })
×
115
                  end
116
               end)
117
               SILE.process(content)
×
118
               SILE.call("dotfill")
×
119
               SILE.typesetter:typeset(options.pageno)
×
120
            end)
121
         )
122
      end)
123
   end)
124

125
   self:registerCommand("tocentry", function (options, content)
4✔
126
      local dest
127
      if SILE.Commands["pdf:destination"] then
×
128
         dest = "dest" .. tostring(SILE.scratch.pdf_destination_counter)
×
129
         SILE.call("pdf:destination", { name = dest })
×
130
         -- Reconstruct a textual representation of the content tree
131
         local title = SILE.typesetter:contentToText(content)
×
132
         SILE.call("pdf:bookmark", { title = title, dest = dest, level = options.level })
×
133
         SILE.scratch.pdf_destination_counter = SILE.scratch.pdf_destination_counter + 1
×
134
      end
135
      SILE.call("info", {
×
136
         category = "toc",
137
         value = {
×
138
            label = SU.ast.stripContentPos(content),
139
            level = (options.level or 1),
140
            number = options.number,
141
            link = dest,
142
         },
143
      })
144
   end)
145

146
   self:registerCommand("tableofcontents:title", function (_, _)
4✔
147
      SU.deprecated("\\tableofcontents:title", "\\fluent{tableofcontents-title}", "0.13.0", "0.14.0")
×
148
   end, "Deprecated")
2✔
149

150
   self:registerCommand("tableofcontents:notocmessage", function (_, _)
4✔
151
      SILE.call("tableofcontents:headerfont", {}, function ()
×
152
         SILE.call("fluent", {}, { "tableofcontents-not-generated" })
×
153
      end)
154
   end)
155

156
   self:registerCommand("tableofcontents:headerfont", function (_, content)
4✔
157
      SILE.call("font", { size = 24, weight = 800 }, content)
×
158
   end)
159

160
   self:registerCommand("tableofcontents:header", function (_, _)
4✔
161
      SILE.call("par")
×
162
      SILE.call("noindent")
×
163
      SILE.call("tableofcontents:headerfont", {}, function ()
×
164
         SILE.call("fluent", {}, { "tableofcontents-title" })
×
165
      end)
166
      SILE.call("medskip")
×
167
   end)
168

169
   self:registerCommand("tableofcontents:footer", function (_, _) end)
2✔
170

171
   self:registerCommand("tableofcontents:level1item", function (_, content)
4✔
172
      SILE.call("bigskip")
×
173
      SILE.call("noindent")
×
174
      SILE.call("font", { size = 14, weight = 800 }, content)
×
175
      SILE.call("medskip")
×
176
   end)
177

178
   self:registerCommand("tableofcontents:level2item", function (_, content)
4✔
179
      SILE.call("noindent")
×
180
      SILE.call("font", { size = 12 }, content)
×
181
      SILE.call("medskip")
×
182
   end)
183

184
   self:registerCommand("tableofcontents:level3item", function (_, content)
4✔
185
      SILE.call("indent")
×
186
      SILE.call("font", { size = 10 }, content)
×
187
      SILE.call("smallskip")
×
188
   end)
189

190
   self:registerCommand("tableofcontents:level1number", function (_, _) end)
2✔
191

192
   self:registerCommand("tableofcontents:level2number", function (_, _) end)
2✔
193

194
   self:registerCommand("tableofcontents:level3number", function (_, _) end)
2✔
195
end
196

197
package.documentation = [[
198
\begin{document}
199
The \autodoc:package{tableofcontents} package provides tools for class authors to
200
create tables of contents (TOCs). When you are writing sectioning commands such
201
as \autodoc:command[check=false]{\chapter} or \autodoc:command[check=false]{\section}, your classes should call the
202
\autodoc:command{\tocentry[level=<number>, number=<strings>]{<title>}}
203
command to register a table of contents entry.
204
At the end of each page the class will call a hook function (\code{moveTocNodes}) that collates the table of contents entries from that pages and records which page they’re on.
205
At the end of the document another hook function (\code{writeToc}) will write this data to a file.
206
The next time the document is built, any use of the \autodoc:command{\tableofcontents} (typically near the beginning of a document) will be able to read that index data and output the TOC.
207
Because the toc entry and page data is not available until after rendering the document,
208
the TOC will not render until at least the second pass.
209
If by chance rendering the TOC itself changes the document pagination (e.g., the TOC spans more than one page) it will be necessary to run SILE a third time to get accurate page numbers shown in the TOC.
210

211
The \autodoc:command{\tableofcontents} command accepts a \autodoc:parameter{depth} option to
212
control the depth of the content added to the table.
213

214
If the \autodoc:package{pdf} package is loaded before using sectioning commands,
215
then a PDF document outline will be generated.
216
Moreover, entries in the table of contents will be active links to the
217
relevant sections. To disable the latter behavior, pass \autodoc:parameter{linking=false} to
218
the \autodoc:command{\tableofcontents} command.
219

220
Class designers can also style the table of contents by overriding the
221
following commands:
222

223
\begin{itemize}
224
\item{\autodoc:command{\tableofcontents:headerfont}: The font used for the header.}
225
\item{\autodoc:command{\tableofcontents:level1item}, \autodoc:command{\tableofcontents:level2item},
226
      etc.: Styling for entries.}
227
\item{\autodoc:command{\tableofcontents:level1number}, \autodoc:command{\tableofcontents:level2number},
228
      etc.: Deciding what to do with entry section number, if defined: by default, nothing (so they
229
      do not show up in the table of contents).}
230
\end{itemize}
231

232
\end{document}
233
]]
2✔
234

235
return package
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc