• 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

73.1
/packages/rules/init.lua
1
local base = require("packages.base")
7✔
2

3
local package = pl.class(base)
7✔
4
package._name = "rules"
7✔
5

6
local function getUnderlineParameters ()
7
   local ot = require("core.opentype-parser")
10✔
8
   local fontoptions = SILE.font.loadDefaults({})
10✔
9
   local face = SILE.font.cache(fontoptions, SILE.shaper.getFace)
10✔
10
   local font = ot.parseFont(face)
10✔
11
   local upem = font.head.unitsPerEm
10✔
12
   local underlinePosition = font.post.underlinePosition / upem * fontoptions.size
10✔
13
   local underlineThickness = font.post.underlineThickness / upem * fontoptions.size
10✔
14
   return underlinePosition, underlineThickness
10✔
15
end
16

17
local function getStrikethroughParameters ()
18
   local ot = require("core.opentype-parser")
5✔
19
   local fontoptions = SILE.font.loadDefaults({})
5✔
20
   local face = SILE.font.cache(fontoptions, SILE.shaper.getFace)
5✔
21
   local font = ot.parseFont(face)
5✔
22
   local upem = font.head.unitsPerEm
5✔
23
   local yStrikeoutPosition = font.os2.yStrikeoutPosition / upem * fontoptions.size
5✔
24
   local yStrikeoutSize = font.os2.yStrikeoutSize / upem * fontoptions.size
5✔
25
   return yStrikeoutPosition, yStrikeoutSize
5✔
26
end
27

28
-- \hfill (from the "plain" class) and \leaders (from the "leaders" package) use glues,
29
-- so we behave the same for hrulefill.
30
local hrulefillglue = pl.class(SILE.nodefactory.hfillglue)
7✔
31
hrulefillglue.raise = SILE.measurement()
14✔
32
hrulefillglue.thickness = SILE.measurement("0.2pt")
14✔
33

34
function hrulefillglue:outputYourself (typesetter, line)
7✔
35
   local outputWidth = SU.rationWidth(self.width, self.width, line.ratio):tonumber()
40✔
36
   local oldx = typesetter.frame.state.cursorX
20✔
37
   typesetter.frame:advancePageDirection(-self.raise)
31✔
38
   typesetter.frame:advanceWritingDirection(outputWidth)
20✔
39
   local newx = typesetter.frame.state.cursorX
20✔
40
   local newy = typesetter.frame.state.cursorY
20✔
41
   SILE.outputter:drawRule(oldx, newy, newx - oldx, self.thickness)
40✔
42
   typesetter.frame:advancePageDirection(self.raise)
20✔
43
end
44

45
function package:_init ()
7✔
46
   base._init(self)
7✔
47
   self:loadPackage("raiselower")
7✔
48
   self:loadPackage("rebox")
7✔
49
end
50

51
function package:registerCommands ()
7✔
52
   self:registerCommand("hrule", function (options, _)
14✔
53
      local width = SU.cast("length", options.width)
28✔
54
      local height = SU.cast("length", options.height)
28✔
55
      local depth = SU.cast("length", options.depth)
28✔
56
      SILE.typesetter:pushHbox({
56✔
57
         width = width:absolute(),
56✔
58
         height = height:absolute(),
56✔
59
         depth = depth:absolute(),
56✔
60
         value = options.src,
28✔
61
         outputYourself = function (node, typesetter, line)
62
            local outputWidth = SU.rationWidth(node.width, node.width, line.ratio)
28✔
63
            typesetter.frame:advancePageDirection(-node.height)
56✔
64
            local oldx = typesetter.frame.state.cursorX
28✔
65
            local oldy = typesetter.frame.state.cursorY
28✔
66
            typesetter.frame:advanceWritingDirection(outputWidth)
28✔
67
            typesetter.frame:advancePageDirection(node.height + node.depth)
56✔
68
            local newx = typesetter.frame.state.cursorX
28✔
69
            local newy = typesetter.frame.state.cursorY
28✔
70
            SILE.outputter:drawRule(oldx, oldy, newx - oldx, newy - oldy)
84✔
71
            typesetter.frame:advancePageDirection(-node.depth)
56✔
72
         end,
73
      })
74
   end, "Draws a blob of ink of width <width>, height <height> and depth <depth>")
35✔
75

76
   self:registerCommand("hrulefill", function (options, _)
14✔
77
      local raise
78
      local thickness
79
      if options.position and options.raise then
20✔
NEW
80
         SU.error("hrulefill cannot have both position and raise parameters")
×
81
      end
82
      if options.thickness then
20✔
83
         thickness = SU.cast("measurement", options.thickness)
16✔
84
      end
85
      if options.position == "underline" then
20✔
86
         local underlinePosition, underlineThickness = getUnderlineParameters()
5✔
87
         thickness = thickness or underlineThickness
5✔
88
         raise = underlinePosition
5✔
89
      elseif options.position == "strikethrough" then
15✔
90
         local yStrikeoutPosition, yStrikeoutSize = getStrikethroughParameters()
5✔
91
         thickness = thickness or yStrikeoutSize
5✔
92
         raise = yStrikeoutPosition + thickness / 2
7✔
93
      elseif options.position then
10✔
NEW
94
         SU.error("Unknown hrulefill position '" .. options.position .. "'")
×
95
      else
96
         raise = SU.cast("measurement", options.raise or "0")
20✔
97
      end
98

99
      SILE.typesetter:pushExplicitGlue(hrulefillglue({
60✔
100
         raise = raise,
20✔
101
         thickness = thickness or SILE.measurement("0.2pt"),
24✔
102
      }))
103
   end, "Add a huge horizontal hrule glue")
27✔
104

105
   self:registerCommand("fullrule", function (options, _)
14✔
106
      local thickness = SU.cast("measurement", options.thickness or "0.2pt")
2✔
107
      local raise = SU.cast("measurement", options.raise or "0.5em")
2✔
108

109
      -- BEGIN DEPRECATION COMPATIBILITY
110
      if options.height then
2✔
NEW
111
         SU.deprecated("\\fullrule[…, height=…]", "\\fullrule[…, thickness=…]", "0.13.1", "0.15.0")
×
NEW
112
         thickness = SU.cast("measurement", options.height)
×
113
      end
114
      if not SILE.typesetter:vmode() then
4✔
NEW
115
         SU.deprecated("\\fullrule in horizontal mode", "\\hrule or \\hrulefill", "0.13.1", "0.15.0")
×
NEW
116
         if options.width then
×
NEW
117
            SU.deprecated("\\fullrule with width", "\\hrule and \\raise", "0.13.1", "0.15.0")
×
NEW
118
            SILE.call("raise", { height = raise }, function ()
×
NEW
119
               SILE.call("hrule", {
×
120
                  height = thickness,
121
                  width = options.width,
122
               })
123
            end)
124
         else
125
            -- This was very broken anyway, as it was overflowing the line.
126
            -- At least we try better...
NEW
127
            SILE.call("hrulefill", { raise = raise, thickness = thickness })
×
128
         end
NEW
129
         return
×
130
      end
131
      if options.width then
2✔
NEW
132
         SU.deprecated("\\fullrule with width", "\\hrule and \\raise", "0.13.1 ", "0.15.0")
×
NEW
133
         SILE.call("raise", { height = raise }, function ()
×
NEW
134
            SILE.call("hrule", {
×
135
               height = thickness,
136
               width = options.width,
137
            })
138
         end)
139
      end
140
      -- END DEPRECATION COMPATIBILITY
141

142
      SILE.typesetter:leaveHmode()
2✔
143
      SILE.call("noindent")
2✔
144
      SILE.call("hrulefill", { raise = raise, thickness = thickness })
2✔
145
      SILE.typesetter:leaveHmode()
2✔
146
   end, "Draw a full width hrule centered on the current line")
9✔
147

148
   self:registerCommand("underline", function (_, content)
14✔
149
      local underlinePosition, underlineThickness = getUnderlineParameters()
5✔
150

151
      local hbox, hlist = SILE.typesetter:makeHbox(content)
5✔
152
      -- Re-wrap the hbox in another hbox responsible for boxing it at output
153
      -- time, when we will know the line contribution and can compute the scaled width
154
      -- of the box, taking into account possible stretching and shrinking.
155
      SILE.typesetter:pushHbox({
10✔
156
         inner = hbox,
5✔
157
         width = hbox.width,
5✔
158
         height = hbox.height,
5✔
159
         depth = hbox.depth,
5✔
160
         outputYourself = function (node, typesetter, line)
161
            local oldX = typesetter.frame.state.cursorX
5✔
162
            local Y = typesetter.frame.state.cursorY
5✔
163

164
            -- Build the original hbox.
165
            -- Cursor will be moved by the actual definitive size.
166
            node.inner:outputYourself(SILE.typesetter, line)
5✔
167
            local newX = typesetter.frame.state.cursorX
5✔
168

169
            -- Output a line.
170
            -- NOTE: According to the OpenType specs, underlinePosition is "the suggested distance of
171
            -- the top of the underline from the baseline" so it seems implied that the thickness
172
            -- should expand downwards
173
            SILE.outputter:drawRule(oldX, Y - underlinePosition, newX - oldX, underlineThickness)
15✔
174
         end,
175
      })
176
      SILE.typesetter:pushHlist(hlist)
5✔
177
   end, "Underlines some content")
12✔
178

179
   self:registerCommand("strikethrough", function (_, content)
14✔
NEW
180
      local yStrikeoutPosition, yStrikeoutSize = getStrikethroughParameters()
×
181

NEW
182
      local hbox, hlist = SILE.typesetter:makeHbox(content)
×
183
      -- Re-wrap the hbox in another hbox responsible for boxing it at output
184
      -- time, when we will know the line contribution and can compute the scaled width
185
      -- of the box, taking into account possible stretching and shrinking.
NEW
186
      SILE.typesetter:pushHbox({
×
187
         inner = hbox,
188
         width = hbox.width,
189
         height = hbox.height,
190
         depth = hbox.depth,
191
         outputYourself = function (node, typesetter, line)
NEW
192
            local oldX = typesetter.frame.state.cursorX
×
NEW
193
            local Y = typesetter.frame.state.cursorY
×
194
            -- Build the original hbox.
195
            -- Cursor will be moved by the actual definitive size.
NEW
196
            node.inner:outputYourself(SILE.typesetter, line)
×
NEW
197
            local newX = typesetter.frame.state.cursorX
×
198
            -- Output a line.
199
            -- NOTE: The OpenType spec is not explicit regarding how the size
200
            -- (thickness) affects the position. We opt to distribute evenly
NEW
201
            SILE.outputter:drawRule(oldX, Y - yStrikeoutPosition - yStrikeoutSize / 2, newX - oldX, yStrikeoutSize)
×
202
         end,
203
      })
NEW
204
      SILE.typesetter:pushHlist(hlist)
×
205
   end, "Strikes out some content")
7✔
206

207
   self:registerCommand("boxaround", function (_, content)
14✔
208
      -- This command was not documented and lacks feature.
209
      -- Plan replacement with a better suited package.
NEW
210
      SU.deprecated("\\boxaround (undocumented)", "\\framebox (package)", "0.12.0")
×
211

NEW
212
      local hbox, hlist = SILE.typesetter:makeHbox(content)
×
213
      -- Re-wrap the hbox in another hbox responsible for boxing it at output
214
      -- time, when we will know the line contribution and can compute the scaled width
215
      -- of the box, taking into account possible stretching and shrinking.
NEW
216
      SILE.typesetter:pushHbox({
×
217
         inner = hbox,
218
         width = hbox.width,
219
         height = hbox.height,
220
         depth = hbox.depth,
221
         outputYourself = function (node, typesetter, line)
NEW
222
            local oldX = typesetter.frame.state.cursorX
×
NEW
223
            local Y = typesetter.frame.state.cursorY
×
224

225
            -- Build the original hbox.
226
            -- Cursor will be moved by the actual definitive size.
NEW
227
            node.inner:outputYourself(SILE.typesetter, line)
×
NEW
228
            local newX = typesetter.frame.state.cursorX
×
229

230
            -- Output a border
231
            -- NOTE: Drawn inside the hbox, so borders overlap with inner content.
NEW
232
            local w = newX - oldX
×
NEW
233
            local h = node.height:tonumber()
×
NEW
234
            local d = node.depth:tonumber()
×
NEW
235
            local thickness = 0.5
×
236

NEW
237
            SILE.outputter:drawRule(oldX, Y + d - thickness, w, thickness)
×
NEW
238
            SILE.outputter:drawRule(oldX, Y - h, w, thickness)
×
NEW
239
            SILE.outputter:drawRule(oldX, Y - h, thickness, h + d)
×
NEW
240
            SILE.outputter:drawRule(oldX + w - thickness, Y - h, thickness, h + d)
×
241
         end,
242
      })
NEW
243
      SILE.typesetter:pushHlist(hlist)
×
244
   end, "Draws a box around some content")
7✔
245
end
246

247
package.documentation = [[
248
\begin{document}
249
The \autodoc:package{rules} package provides several line-drawing commands.
250

251
The \autodoc:command{\hrule} command draws a blob of ink of a given \autodoc:parameter{width} (length), \autodoc:parameter{height} (above the current baseline), and \autodoc:parameter{depth} (below the current baseline).
252
Such rules are horizontal boxes, placed along the baseline of a line of text and treated just like other text to be output.
253
So, they can appear in the middle of a paragraph, like this:
254
\hrule[width=20pt, height=0.5pt]
255
(That one was generated with \autodoc:command{\hrule[width=20pt, height=0.5pt]}.)
256

257
The \autodoc:command{\underline} command \underline{underlines} its content.
258

259
The \autodoc:command{\strikethrough} command \strikethrough{strikes} its content.
260

261
\autodoc:note{The position and thickness of the underlines and strikethroughs are based on the metrics of the current font, honoring the values defined by the type designer.}
262

263
The \autodoc:command{\hrulefill} inserts an infinite horizontal rubber, similar to an \autodoc:command{\hfill}, but—as its name implies—filled with a rule (that is, a solid line).
264
By default, it stands on the baseline and has a thickness of 0.2pt, below the baseline.
265
It supports optional parameters \autodoc:parameter{raise=<dimension>} and \autodoc:parameter{thickness=<dimension>} to adjust the position and thickness of the line, respectively.
266
The former accepts a negative measurement, to lower the line.
267
Alternatively, use the \autodoc:parameter{position} option, which can be set to \code{underline} or \code{strikethrough}.
268
In that case, it honors the current font metrics and the line is drawn at the appropriate position and, by default, with the relevant thickness.
269
You can still set a custom thickness with the \autodoc:parameter{thickness} parameter.
270

271
For instance, \autodoc:command{\hrulefill[position=underline]} gives:
272
\hrulefill[position=underline]
273

274
Finally, \autodoc:command{\fullrule} draws a thin standalone rule across the width of a full text line.
275
Accepted parameters are \autodoc:parameter{raise} and \autodoc:parameter{thickness}, with the same meanings as above.
276
\end{document}
277
]]
7✔
278

279
return package
7✔
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