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

sile-typesetter / sile / 9304060604

30 May 2024 02:07PM UTC coverage: 74.124% (-0.6%) from 74.707%
9304060604

push

github

alerque
style: Reformat Lua with stylua

8104 of 11995 new or added lines in 184 files covered. (67.56%)

15 existing lines in 11 files now uncovered.

12444 of 16788 relevant lines covered (74.12%)

7175.1 hits per line

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

79.79
/classes/base.lua
1
local class = pl.class()
181✔
2
class.type = "class"
181✔
3
class._name = "base"
181✔
4

5
class._initialized = false
181✔
6
class.deferredLegacyInit = {}
181✔
7
class.deferredInit = {}
181✔
8
class.pageTemplate = { frames = {}, firstContentFrame = nil }
181✔
9
class.defaultFrameset = {}
181✔
10
class.firstContentFrame = "page"
181✔
11
class.options = setmetatable({}, {
362✔
12
   _opts = {},
181✔
13
   __newindex = function (self, key, value)
14
      local opts = getmetatable(self)._opts
1,115✔
15
      if type(opts[key]) == "function" then
1,115✔
16
         opts[key](class, value)
758✔
17
      elseif type(value) == "function" then
736✔
18
         opts[key] = value
735✔
19
      elseif type(key) == "number" then
1✔
20
         return nil
1✔
21
      else
NEW
22
         SU.error("Attempted to set an undeclared class option '" .. key .. "'")
×
23
      end
24
   end,
25
   __index = function (self, key)
26
      if key == "super" then
192✔
NEW
27
         return nil
×
28
      end
29
      if type(key) == "number" then
192✔
NEW
30
         return nil
×
31
      end
32
      local opt = getmetatable(self)._opts[key]
192✔
33
      if type(opt) == "function" then
192✔
34
         return opt(class)
192✔
35
      elseif opt then
×
NEW
36
         return opt
×
37
      else
NEW
38
         SU.error("Attempted to get an undeclared class option '" .. key .. "'")
×
39
      end
40
   end,
41
})
181✔
42
class.hooks = {
181✔
43
   newpage = {},
181✔
44
   endpage = {},
181✔
45
   finish = {},
181✔
46
}
181✔
47

48
class.packages = {}
181✔
49

50
function class:_init (options)
181✔
51
   SILE.scratch.half_initialized_class = self
181✔
52
   if self == options then
181✔
NEW
53
      options = {}
×
54
   end
55
   SILE.languageSupport.loadLanguage("und") -- preload for unlocalized fallbacks
181✔
56
   self:declareOptions()
181✔
57
   self:registerRawHandlers()
181✔
58
   self:declareSettings()
181✔
59
   self:registerCommands()
181✔
60
   self:setOptions(options)
181✔
61
   self:declareFrames(self.defaultFrameset)
181✔
62
   self:registerPostinit(function (self_)
362✔
63
      if type(self.firstContentFrame) == "string" then
181✔
64
         self_.pageTemplate.firstContentFrame = self_.pageTemplate.frames[self_.firstContentFrame]
181✔
65
      end
66
      local frame = self_:initialFrame()
181✔
67
      SILE.typesetter = SILE.typesetters.base(frame)
362✔
68
      SILE.typesetter:registerPageEndHook(function ()
362✔
69
         SU.debug("frames", function ()
460✔
NEW
70
            for _, v in pairs(SILE.frames) do
×
NEW
71
               SILE.outputter:debugFrame(v)
×
72
            end
NEW
73
            return "Drew debug outlines around frames"
×
74
         end)
75
      end)
76
   end)
77
end
78

79
function class:_post_init ()
181✔
80
   self._initialized = true
181✔
81
   for i, func in ipairs(self.deferredInit) do
444✔
82
      func(self)
263✔
83
      self.deferredInit[i] = nil
263✔
84
   end
85
   SILE.scratch.half_initialized_class = nil
181✔
86
end
87

88
function class:setOptions (options)
181✔
89
   options = options or {}
181✔
90
   -- Classes that add options with dependencies should explicitly handle them, then exempt them from furthur processing.
91
   -- The landscape option is handled explicitly before papersize, then the "rest" of options that are not interdependent.
92
   self.options.landscape = SU.boolean(options.landscape, false)
362✔
93
   options.landscape = nil
181✔
94
   self.options.papersize = options.papersize or "a4"
181✔
95
   options.papersize = nil
181✔
96
   for option, value in pairs(options) do
199✔
97
      self.options[option] = value
18✔
98
   end
99
end
100

101
function class:declareOption (option, setter)
181✔
102
   rawset(getmetatable(self.options)._opts, option, nil)
735✔
103
   self.options[option] = setter
735✔
104
end
105

106
function class:declareOptions ()
181✔
107
   self:declareOption("class", function (_, name)
362✔
NEW
108
      if name then
×
NEW
109
         if self._legacy then
×
NEW
110
            self._name = name
×
NEW
111
         elseif name ~= self._name then
×
NEW
112
            SU.error("Cannot change class name after instantiation, derive a new class instead.")
×
113
         end
114
      end
NEW
115
      return self._name
×
116
   end)
117
   self:declareOption("landscape", function (_, landscape)
362✔
118
      if landscape then
363✔
119
         self.landscape = landscape
1✔
120
      end
121
      return self.landscape
363✔
122
   end)
123
   self:declareOption("papersize", function (_, size)
362✔
124
      if size then
181✔
125
         self.papersize = size
181✔
126
         SILE.documentState.paperSize = SILE.papersize(size, self.options.landscape)
543✔
127
         SILE.documentState.orgPaperSize = SILE.documentState.paperSize
181✔
128
         SILE.newFrame({
362✔
129
            id = "page",
130
            left = 0,
131
            top = 0,
132
            right = SILE.documentState.paperSize[1],
181✔
133
            bottom = SILE.documentState.paperSize[2],
181✔
134
         })
135
      end
136
      return self.papersize
181✔
137
   end)
138
end
139

140
function class.declareSettings (_)
181✔
141
   SILE.settings:declare({
181✔
142
      parameter = "current.parindent",
143
      type = "glue or nil",
144
      default = nil,
145
      help = "Glue at start of paragraph",
146
   })
147
   SILE.settings:declare({
181✔
148
      parameter = "current.hangIndent",
149
      type = "measurement or nil",
150
      default = nil,
151
      help = "Size of hanging indent",
152
   })
153
   SILE.settings:declare({
181✔
154
      parameter = "current.hangAfter",
155
      type = "integer or nil",
156
      default = nil,
157
      help = "Number of lines affected by handIndent",
158
   })
159
end
160

161
function class:loadPackage (packname, options)
181✔
162
   local pack = require(("packages.%s"):format(packname))
991✔
163
   if type(pack) == "table" and pack.type == "package" then -- new package
991✔
164
      self.packages[pack._name] = pack(options)
1,982✔
165
   else -- legacy package
NEW
166
      self:initPackage(pack, options)
×
167
   end
168
end
169

170
function class:initPackage (pack, options)
181✔
NEW
171
   SU.deprecated(
×
172
      "class:initPackage(options)",
173
      "package(options)",
174
      "0.14.0",
175
      "0.16.0",
NEW
176
      [[
×
177
  This package appears to be a legacy format package. It returns a table
178
  and expects SILE to guess about what to do. New packages inherit
179
  from the base class and have a constructor function (_init) that
NEW
180
  automatically handles setup.]]
×
181
   )
NEW
182
   if type(pack) == "table" then
×
NEW
183
      if pack.exports then
×
NEW
184
         pl.tablex.update(self, pack.exports)
×
185
      end
NEW
186
      if type(pack.declareSettings) == "function" then
×
NEW
187
         pack.declareSettings(self)
×
188
      end
NEW
189
      if type(pack.registerRawHandlers) == "function" then
×
NEW
190
         pack.registerRawHandlers(self)
×
191
      end
NEW
192
      if type(pack.registerCommands) == "function" then
×
NEW
193
         pack.registerCommands(self)
×
194
      end
NEW
195
      if type(pack.init) == "function" then
×
NEW
196
         self:registerPostinit(pack.init, options)
×
197
      end
198
   end
199
end
200

201
function class:registerLegacyPostinit (func, options)
181✔
NEW
202
   if self._initialized then
×
NEW
203
      return func(self, options)
×
204
   end
NEW
205
   table.insert(self.deferredLegacyInit, function (_)
×
UNCOV
206
      func(self, options)
×
207
   end)
208
end
209

210
function class:registerPostinit (func, options)
181✔
211
   if self._initialized then
287✔
212
      return func(self, options)
24✔
213
   end
214
   table.insert(self.deferredInit, function (_)
526✔
215
      func(self, options)
263✔
216
   end)
217
end
218

219
function class:registerHook (category, func)
181✔
220
   for _, func_ in ipairs(self.hooks[category]) do
781✔
221
      if func_ == func then
246✔
222
         return
1✔
223
         --[[ See https://github.com/sile-typesetter/sile/issues/1531
224
      return SU.warn("Attempted to set the same function hook twice, probably unintended, skipping.")
225
      -- If the same function signature is already set a package is probably being
226
      -- re-initialized. Ditch the first instance of the hook so that it runs in
227
      -- the order of last initialization.
228
      self.hooks[category][_] = nil
229
      ]]
230
      end
231
   end
232
   table.insert(self.hooks[category], func)
535✔
233
end
234

235
function class:runHooks (category, options)
181✔
236
   for _, func in ipairs(self.hooks[category]) do
978✔
237
      SU.debug("classhooks", "Running hook from", category, options and "with options " .. #options)
506✔
238
      func(self, options)
506✔
239
   end
240
end
241

242
function class.registerCommand (_, name, func, help, pack)
181✔
243
   SILE.Commands[name] = func
18,594✔
244
   if not pack then
18,594✔
245
      local where = debug.getinfo(2).source
18,579✔
246
      pack = where:match("(%w+).lua")
18,579✔
247
   end
248
   --if not help and not pack:match(".sil") then SU.error("Could not define command '"..name.."' (in package "..pack..") - no help text" ) end
249
   SILE.Help[name] = {
18,594✔
250
      description = help,
18,594✔
251
      where = pack,
18,594✔
252
   }
18,594✔
253
end
254

255
function class.registerRawHandler (_, format, callback)
181✔
256
   SILE.rawHandlers[format] = callback
185✔
257
end
258

259
function class:registerRawHandlers ()
181✔
260
   self:registerRawHandler("text", function (_, content)
362✔
261
      SILE.settings:temporarily(function ()
2✔
262
         SILE.settings:set("typesetter.parseppattern", "\n")
1✔
263
         SILE.settings:set("typesetter.obeyspaces", true)
1✔
264
         SILE.typesetter:typeset(content[1])
1✔
265
      end)
266
   end)
267
end
268

269
local function packOptions (options)
270
   local relevant = pl.tablex.copy(options)
150✔
271
   relevant.src = nil
150✔
272
   relevant.format = nil
150✔
273
   relevant.module = nil
150✔
274
   relevant.require = nil
150✔
275
   return relevant
150✔
276
end
277

278
function class:registerCommands ()
181✔
279
   local function replaceProcessBy (replacement, tree)
280
      if type(tree) ~= "table" then
175✔
281
         return tree
69✔
282
      end
283
      local ret = pl.tablex.deepcopy(tree)
106✔
284
      if tree.command == "process" then
106✔
285
         return replacement
7✔
286
      else
287
         for i, child in ipairs(tree) do
231✔
288
            ret[i] = replaceProcessBy(replacement, child)
264✔
289
         end
290
         return ret
99✔
291
      end
292
   end
293

294
   self:registerCommand("define", function (options, content)
362✔
295
      SU.required(options, "command", "defining command")
15✔
296
      if type(content) == "function" then
15✔
297
         -- A macro defined as a function can take no argument, so we register
298
         -- it as-is.
NEW
299
         self:registerCommand(options["command"], content)
×
NEW
300
         return
×
301
      elseif options.command == "process" then
15✔
NEW
302
         SU.warn("Did you mean to re-definine the `\\process` macro? That probably won't go well.")
×
303
      end
304
      self:registerCommand(options["command"], function (_, inner_content)
30✔
305
         SU.debug("macros", "Processing macro \\" .. options["command"])
43✔
306
         local macroArg
307
         if type(inner_content) == "function" then
43✔
308
            macroArg = inner_content
2✔
309
         elseif type(inner_content) == "table" then
41✔
310
            macroArg = pl.tablex.copy(inner_content)
78✔
311
            macroArg.command = nil
39✔
312
            macroArg.id = nil
39✔
313
         elseif inner_content == nil then
2✔
314
            macroArg = {}
2✔
315
         else
NEW
316
            SU.error(
×
NEW
317
               "Unhandled content type " .. type(inner_content) .. " passed to macro \\" .. options["command"],
×
318
               true
319
            )
320
         end
321
         -- Replace every occurrence of \process in `content` (the macro
322
         -- body) with `macroArg`, then have SILE go through the new `content`.
323
         local newContent = replaceProcessBy(macroArg, content)
43✔
324
         SILE.process(newContent)
43✔
325
         SU.debug("macros", "Finished processing \\" .. options["command"])
43✔
326
      end, options.help, SILE.currentlyProcessingFile)
58✔
327
   end, "Define a new macro. \\define[command=example]{ ... \\process }")
196✔
328

329
   -- A utility function that allows SILE.call() to be used as a noop wrapper.
330
   self:registerCommand("noop", function (_, content)
362✔
331
      SILE.process(content)
7✔
332
   end)
333

334
   -- The document (SIL) or sile (XML) command is always the sigular leaf at the
335
   -- top level of our AST. The work you might expect to see happen here is
336
   -- actually handled by SILE.inputter:classInit() before we get here, so these
337
   -- are just pass through functions. Theoretically, this could be a useful
338
   -- point to hook into-especially for included documents.
339
   self:registerCommand("document", function (_, content)
362✔
NEW
340
      SILE.process(content)
×
341
   end)
342
   self:registerCommand("sile", function (_, content)
362✔
NEW
343
      SILE.process(content)
×
344
   end)
345

346
   self:registerCommand("comment", function (_, _) end, "Ignores any text within this command's body.")
181✔
347

348
   self:registerCommand("process", function ()
362✔
NEW
349
      SU.error("Encountered unsubstituted \\process.")
×
350
   end, "Within a macro definition, processes the contents of the macro body.")
181✔
351

352
   self:registerCommand("script", function (options, content)
362✔
353
      local packopts = packOptions(options)
39✔
354
      if SU.hasContent(content) then
78✔
355
         return SILE.processString(content[1], options.format or "lua", nil, packopts)
33✔
356
      elseif options.src then
6✔
357
         return SILE.require(options.src)
6✔
358
      else
NEW
359
         SU.error("\\script function requires inline content or a src file path")
×
NEW
360
         return SILE.processString(content[1], options.format or "lua", nil, packopts)
×
361
      end
362
   end, "Runs lua code. The code may be supplied either inline or using src=...")
181✔
363

364
   self:registerCommand("include", function (options, content)
362✔
365
      local packopts = packOptions(options)
1✔
366
      if SU.hasContent(content) then
2✔
NEW
367
         local doc = SU.contentToString(content)
×
NEW
368
         return SILE.processString(doc, options.format, nil, packopts)
×
369
      elseif options.src then
1✔
370
         return SILE.processFile(options.src, options.format, packopts)
1✔
371
      else
NEW
372
         SU.error("\\include function requires inline content or a src file path")
×
373
      end
374
   end, "Includes a content file for processing.")
181✔
375

376
   self:registerCommand(
362✔
377
      "lua",
181✔
378
      function (options, content)
379
         local packopts = packOptions(options)
4✔
380
         if SU.hasContent(content) then
8✔
381
            local doc = SU.contentToString(content)
4✔
382
            return SILE.processString(doc, "lua", nil, packopts)
4✔
NEW
383
         elseif options.src then
×
NEW
384
            return SILE.processFile(options.src, "lua", packopts)
×
NEW
385
         elseif options.require then
×
NEW
386
            local module = SU.required(options, "require", "lua")
×
NEW
387
            return require(module)
×
388
         else
NEW
389
            SU.error("\\lua function requires inline content or a src file path or a require module name")
×
390
         end
391
      end,
392
      "Run Lua code. The code may be supplied either inline, using require=... for a Lua module, or using src=... for a file path"
393
   )
181✔
394

395
   self:registerCommand("sil", function (options, content)
362✔
NEW
396
      local packopts = packOptions(options)
×
NEW
397
      if SU.hasContent(content) then
×
NEW
398
         local doc = SU.contentToString(content)
×
NEW
399
         return SILE.processString(doc, "sil")
×
NEW
400
      elseif options.src then
×
NEW
401
         return SILE.processFile(options.src, "sil", packopts)
×
402
      else
NEW
403
         SU.error("\\sil function requires inline content or a src file path")
×
404
      end
405
   end, "Process sil content. The content may be supplied either inline or using src=...")
181✔
406

407
   self:registerCommand("xml", function (options, content)
362✔
NEW
408
      local packopts = packOptions(options)
×
NEW
409
      if SU.hasContent(content) then
×
NEW
410
         local doc = SU.contentToString(content)
×
NEW
411
         return SILE.processString(doc, "xml", nil, packopts)
×
NEW
412
      elseif options.src then
×
NEW
413
         return SILE.processFile(options.src, "xml", packopts)
×
414
      else
NEW
415
         SU.error("\\xml function requires inline content or a src file path")
×
416
      end
417
   end, "Process xml content. The content may be supplied either inline or using src=...")
181✔
418

419
   self:registerCommand(
362✔
420
      "use",
181✔
421
      function (options, content)
422
         local packopts = packOptions(options)
106✔
423
         if content[1] and string.len(content[1]) > 0 then
106✔
NEW
424
            local doc = SU.contentToString(content)
×
NEW
425
            SILE.processString(doc, "lua", nil, packopts)
×
426
         else
427
            if options.src then
106✔
NEW
428
               SU.warn(
×
429
                  "Use of 'src' with \\use is discouraged because some of it's path handling\n  will eventually be deprecated. Use 'module' instead when possible."
430
               )
NEW
431
               SILE.processFile(options.src, "lua", packopts)
×
432
            else
433
               local module = SU.required(options, "module", "use")
106✔
434
               SILE.use(module, packopts)
106✔
435
            end
436
         end
437
      end,
438
      "Load and initialize a SILE module (can be a package, a shaper, a typesetter, or whatever). Use module=... to specif what to load or include module code inline."
439
   )
181✔
440

441
   self:registerCommand("raw", function (options, content)
362✔
442
      local rawtype = SU.required(options, "type", "raw")
4✔
443
      local handler = SILE.rawHandlers[rawtype]
4✔
444
      if not handler then
4✔
NEW
445
         SU.error("No inline handler for '" .. rawtype .. "'")
×
446
      end
447
      handler(options, content)
4✔
448
   end, "Invoke a raw passthrough handler")
185✔
449

450
   self:registerCommand("pagetemplate", function (options, content)
362✔
451
      SILE.typesetter:pushState()
8✔
452
      SILE.documentState.thisPageTemplate = { frames = {} }
8✔
453
      SILE.process(content)
8✔
454
      SILE.documentState.thisPageTemplate.firstContentFrame = SILE.getFrame(options["first-content-frame"])
16✔
455
      SILE.typesetter:initFrame(SILE.documentState.thisPageTemplate.firstContentFrame)
8✔
456
      SILE.typesetter:popState()
8✔
457
   end, "Defines a new page template for the current page and sets the typesetter to use it.")
189✔
458

459
   self:registerCommand("frame", function (options, _)
362✔
460
      SILE.documentState.thisPageTemplate.frames[options.id] = SILE.newFrame(options)
62✔
461
   end, "Declares (or re-declares) a frame on this page.")
212✔
462

463
   self:registerCommand("penalty", function (options, _)
362✔
464
      if SU.boolean(options.vertical, false) and not SILE.typesetter:vmode() then
593✔
465
         SILE.typesetter:leaveHmode()
4✔
466
      end
467
      if SILE.typesetter:vmode() then
570✔
468
         SILE.typesetter:pushVpenalty({ penalty = tonumber(options.penalty) })
454✔
469
      else
470
         SILE.typesetter:pushPenalty({ penalty = tonumber(options.penalty) })
58✔
471
      end
472
   end, "Inserts a penalty node. Option is penalty= for the size of the penalty.")
466✔
473

474
   self:registerCommand("discretionary", function (options, _)
362✔
475
      local discretionary = SILE.nodefactory.discretionary({})
74✔
476
      if options.prebreak then
74✔
477
         local hbox = SILE.typesetter:makeHbox({ options.prebreak })
74✔
478
         discretionary.prebreak = { hbox }
74✔
479
      end
480
      if options.postbreak then
74✔
481
         local hbox = SILE.typesetter:makeHbox({ options.postbreak })
48✔
482
         discretionary.postbreak = { hbox }
48✔
483
      end
484
      if options.replacement then
74✔
485
         local hbox = SILE.typesetter:makeHbox({ options.replacement })
50✔
486
         discretionary.replacement = { hbox }
50✔
487
      end
488
      table.insert(SILE.typesetter.state.nodes, discretionary)
74✔
489
   end, "Inserts a discretionary node.")
255✔
490

491
   self:registerCommand("glue", function (options, _)
362✔
492
      local width = SU.cast("length", options.width):absolute()
118✔
493
      SILE.typesetter:pushGlue(width)
59✔
494
   end, "Inserts a glue node. The width option denotes the glue dimension.")
240✔
495

496
   self:registerCommand("kern", function (options, _)
362✔
497
      local width = SU.cast("length", options.width):absolute()
180✔
498
      SILE.typesetter:pushHorizontal(SILE.nodefactory.kern(width))
180✔
499
   end, "Inserts a glue node. The width option denotes the glue dimension.")
271✔
500

501
   self:registerCommand("skip", function (options, _)
362✔
502
      options.discardable = SU.boolean(options.discardable, false)
58✔
503
      options.height = SILE.length(options.height):absolute()
87✔
504
      SILE.typesetter:leaveHmode()
29✔
505
      if options.discardable then
29✔
NEW
506
         SILE.typesetter:pushVglue(options)
×
507
      else
508
         SILE.typesetter:pushExplicitVglue(options)
29✔
509
      end
510
   end, "Inserts vertical skip. The height options denotes the skip dimension.")
210✔
511

512
   self:registerCommand("par", function (_, _)
362✔
513
      SILE.typesetter:endline()
292✔
514
   end, "Ends the current paragraph.")
473✔
515
end
516

517
function class:initialFrame ()
181✔
518
   SILE.documentState.thisPageTemplate = pl.tablex.deepcopy(self.pageTemplate)
472✔
519
   SILE.frames = { page = SILE.frames.page }
236✔
520
   for k, v in pairs(SILE.documentState.thisPageTemplate.frames) do
1,023✔
521
      SILE.frames[k] = v
787✔
522
   end
523
   if not SILE.documentState.thisPageTemplate.firstContentFrame then
236✔
NEW
524
      SILE.documentState.thisPageTemplate.firstContentFrame = SILE.frames[self.firstContentFrame]
×
525
   end
526
   SILE.documentState.thisPageTemplate.firstContentFrame:invalidate()
236✔
527
   return SILE.documentState.thisPageTemplate.firstContentFrame
236✔
528
end
529

530
function class:declareFrame (id, spec)
181✔
531
   spec.id = id
592✔
532
   if spec.solve then
592✔
NEW
533
      self.pageTemplate.frames[id] = spec
×
534
   else
535
      self.pageTemplate.frames[id] = SILE.newFrame(spec)
1,184✔
536
   end
537
   --   next = spec.next,
538
   --   left = spec.left and fW(spec.left),
539
   --   right = spec.right and fW(spec.right),
540
   --   top = spec.top and fH(spec.top),
541
   --   bottom = spec.bottom and fH(spec.bottom),
542
   --   height = spec.height and fH(spec.height),
543
   --   width = spec.width and fH(spec.width),
544
   --   id = id
545
   -- })
546
end
547

548
function class:declareFrames (specs)
181✔
549
   if specs then
181✔
550
      for k, v in pairs(specs) do
757✔
551
         self:declareFrame(k, v)
576✔
552
      end
553
   end
554
end
555

556
-- WARNING: not called as class method
557
function class.newPar (typesetter)
181✔
558
   local parindent = SILE.settings:get("current.parindent") or SILE.settings:get("document.parindent")
1,706✔
559
   -- See https://github.com/sile-typesetter/sile/issues/1361
560
   -- The parindent *cannot* be pushed non-absolutized, as it may be evaluated
561
   -- outside the (possibly temporary) setting scope where it was used for line
562
   -- breaking.
563
   -- Early absolutization can be problematic sometimes, but here we do not
564
   -- really have the choice.
565
   -- As of problematic cases, consider a parindent that would be defined in a
566
   -- frame-related unit (%lw, %fw, etc.). If a frame break occurs and the next
567
   -- frame has a different width, the parindent won't be re-evaluated in that
568
   -- new frame context. However, defining a parindent in such a unit is quite
569
   -- unlikely. And anyway pushback() has plenty of other issues.
570
   typesetter:pushGlue(parindent:absolute())
1,706✔
571
   SILE.settings:set("current.parindent", nil)
853✔
572
   local hangIndent = SILE.settings:get("current.hangIndent")
853✔
573
   if hangIndent then
853✔
574
      SILE.settings:set("linebreak.hangIndent", hangIndent)
11✔
575
   end
576
   local hangAfter = SILE.settings:get("current.hangAfter")
853✔
577
   if hangAfter then
853✔
578
      SILE.settings:set("linebreak.hangAfter", hangAfter)
11✔
579
   end
580
end
581

582
-- WARNING: not called as class method
583
function class.endPar (typesetter)
181✔
584
   typesetter:pushVglue(SILE.settings:get("document.parskip"))
1,672✔
585
   if SILE.settings:get("current.hangIndent") then
1,672✔
586
      SILE.settings:set("current.hangIndent", nil)
10✔
587
      SILE.settings:set("linebreak.hangIndent", nil)
10✔
588
   end
589
   if SILE.settings:get("current.hangAfter") then
1,672✔
590
      SILE.settings:set("current.hangAfter", nil)
10✔
591
      SILE.settings:set("linebreak.hangAfter", nil)
10✔
592
   end
593
end
594

595
function class:newPage ()
181✔
596
   SILE.outputter:newPage()
55✔
597
   self:runHooks("newpage")
55✔
598
   -- Any other output-routiney things will be done here by inheritors
599
   return self:initialFrame()
55✔
600
end
601

602
function class:endPage ()
181✔
603
   SILE.typesetter.frame:leave(SILE.typesetter)
236✔
604
   self:runHooks("endpage")
236✔
605
   -- I'm trying to call up a new frame here, don't cause a page break in the current one
606
   -- SILE.typesetter:leaveHmode()
607
   -- Any other output-routiney things will be done here by inheritors
608
end
609

610
function class:finish ()
181✔
611
   SILE.inputter:postamble()
181✔
612
   SILE.call("vfill")
181✔
613
   while not SILE.typesetter:isQueueEmpty() do
724✔
614
      SILE.call("supereject")
181✔
615
      SILE.typesetter:leaveHmode(true)
181✔
616
      SILE.typesetter:buildPage()
181✔
617
      if not SILE.typesetter:isQueueEmpty() then
362✔
618
         SILE.typesetter:initNextFrame()
5✔
619
      end
620
   end
621
   SILE.typesetter:runHooks("pageend") -- normally run by the typesetter
181✔
622
   self:endPage()
181✔
623
   if SILE.typesetter and not SILE.typesetter:isQueueEmpty() then
362✔
NEW
624
      SU.error("Queues are not empty as expected after ending last page", true)
×
625
   end
626
   SILE.outputter:finish()
181✔
627
   self:runHooks("finish")
181✔
628
end
629

630
return class
181✔
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

© 2025 Coveralls, Inc