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

sile-typesetter / sile / 7242393151

18 Dec 2023 01:24AM UTC coverage: 68.08% (-6.5%) from 74.62%
7242393151

Pull #1940

github

web-flow
chore(deps): Bump actions/upload-artifact from 3 to 4

Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #1940: chore(deps): Bump actions/upload-artifact from 3 to 4

10743 of 15780 relevant lines covered (68.08%)

6752.38 hits per line

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

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

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

6
local function getUnderlineParameters ()
7
  local ot = require("core.opentype-parser")
5✔
8
  local fontoptions = SILE.font.loadDefaults({})
5✔
9
  local face = SILE.font.cache(fontoptions, SILE.shaper.getFace)
5✔
10
  local font = ot.parseFont(face)
5✔
11
  local upem = font.head.unitsPerEm
5✔
12
  local underlinePosition = font.post.underlinePosition / upem * fontoptions.size
5✔
13
  local underlineThickness = font.post.underlineThickness / upem * fontoptions.size
5✔
14
  return underlinePosition, underlineThickness
5✔
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)
4✔
31
hrulefillglue.raise = SILE.measurement()
8✔
32
hrulefillglue.thickness = SILE.measurement("0.2pt")
8✔
33

34
function hrulefillglue:outputYourself (typesetter, line)
4✔
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 ()
4✔
46
  base._init(self)
4✔
47
  self:loadPackage("raiselower")
4✔
48
  self:loadPackage("rebox")
4✔
49
end
50

51
function package:registerCommands ()
4✔
52

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

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

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

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

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

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

149
  self:registerCommand("underline", function (_, content)
8✔
150
    local underlinePosition, underlineThickness = getUnderlineParameters()
×
151

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

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

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

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

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

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

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

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

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

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

247
end
248

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

253
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).
254
Such rules are horizontal boxes, placed along the baseline of a line of text and treated just like other text to be output.
255
So, they can appear in the middle of a paragraph, like this:
256
\hrule[width=20pt, height=0.5pt]
257
(That one was generated with \autodoc:command{\hrule[width=20pt, height=0.5pt]}.)
258

259
The \autodoc:command{\underline} command \underline{underlines} its content.
260

261
The \autodoc:command{\strikethrough} command \strikethrough{strikes} its content.
262

263
\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.}
264

265
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).
266
By default, it stands on the baseline and has a thickness of 0.2pt, below the baseline.
267
It supports optional parameters \autodoc:parameter{raise=<dimension>} and \autodoc:parameter{thickness=<dimension>} to adjust the position and thickness of the line, respectively.
268
The former accepts a negative measurement, to lower the line.
269
Alternatively, use the \autodoc:parameter{position} option, which can be set to \code{underline} or \code{strikethrough}.
270
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.
271
You can still set a custom thickness with the \autodoc:parameter{thickness} parameter.
272

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

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

281
return package
4✔
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