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

sile-typesetter / sile / 14860011647

06 May 2025 12:44PM UTC coverage: 67.057% (+32.5%) from 34.559%
14860011647

push

github

alerque
chore(typesetters): Fixup access to class from typesetter functions

7 of 7 new or added lines in 2 files covered. (100.0%)

1344 existing lines in 103 files now uncovered.

14880 of 22190 relevant lines covered (67.06%)

11549.16 hits per line

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

75.28
/packages/url/init.lua
1
local base = require("packages.base")
1✔
2

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

6
-- URL escape sequence, URL fragment:
7
local preferBreakBefore = "%#"
1✔
8
-- URL path elements, URL query arguments, acceptable extras:
9
local preferBreakAfter = ":/.;?&=!_-"
1✔
10
-- URL scheme:
11
local alwaysBreakAfter = ":" -- Must have only one character here!
1✔
12

13
local escapeRegExpMinimal = function (str)
14
   -- Minimalist = just what's needed for the above strings
15
   return string.gsub(str, "([%.%?%-%%])", "%%%1")
13✔
16
end
17

18
local breakPattern = "[" .. escapeRegExpMinimal(preferBreakBefore .. preferBreakAfter .. alwaysBreakAfter) .. "]"
2✔
19

20
function package:_init ()
1✔
21
   base._init(self)
1✔
22
   self:loadPackage("inputfilter")
1✔
23
   self:loadPackage("pdf")
1✔
24
end
25

26
function package:declareSettings ()
1✔
27
   self.settings:declare({
2✔
28
      parameter = "url.linebreak.primaryPenalty",
29
      type = "integer",
30
      default = 100,
31
      help = "Penalty for breaking lines in URLs at preferred breakpoints",
32
   })
33
   self.settings:declare({
2✔
34
      parameter = "url.linebreak.secondaryPenalty",
35
      type = "integer",
36
      default = 200,
37
      help = "Penalty for breaking lines in URLs at tolerable breakpoints (should be higher than url.linebreak.primaryPenalty)",
38
   })
39
end
40

41
function package:registerCommands ()
1✔
42
   self.commands:register("href", function (options, content)
3✔
43
      if options.src then
×
44
         SILE.call("pdf:link", {
×
45
            dest = options.src,
46
            external = true,
47
            borderwidth = options.borderwidth,
48
            borderstyle = options.borderstyle,
49
            bordercolor = options.bordercolor,
50
            borderoffset = options.borderoffset,
UNCOV
51
         }, content)
×
52
      else
UNCOV
53
         options.src = content[1]
×
54
         SILE.call("pdf:link", {
×
55
            dest = options.src,
56
            external = true,
57
            borderwidth = options.borderwidth,
58
            borderstyle = options.borderstyle,
59
            bordercolor = options.bordercolor,
60
            borderoffset = options.borderoffset,
61
         }, function (_, _)
UNCOV
62
            SILE.call("url", { language = options.language }, content)
×
63
         end)
64
      end
65
   end, "Inserts a PDF hyperlink.")
1✔
66

67
   local urlFilter = function (node, content, options)
68
      if type(node) == "table" then
2✔
69
         return node
×
70
      end
71
      local result = {}
2✔
72
      for token in SU.gtoke(node, breakPattern) do
24✔
73
         if token.string then
20✔
74
            result[#result + 1] = token.string
8✔
75
         else
76
            if string.find(preferBreakBefore, escapeRegExpMinimal(token.separator)) then
24✔
77
               -- Accepts breaking before, and at the extreme worst after.
UNCOV
78
               result[#result + 1] = self.class.packages.inputfilter:createCommand(
×
79
                  content.pos,
×
80
                  content.col,
×
81
                  content.lno,
×
82
                  "penalty",
UNCOV
83
                  { penalty = options.primaryPenalty }
×
84
               )
UNCOV
85
               result[#result + 1] = token.separator
×
86
               result[#result + 1] = self.class.packages.inputfilter:createCommand(
×
87
                  content.pos,
×
88
                  content.col,
×
89
                  content.lno,
×
90
                  "penalty",
UNCOV
91
                  { penalty = options.worsePenalty }
×
92
               )
93
            elseif token.separator == alwaysBreakAfter then
12✔
94
               -- Accept breaking after (only).
95
               result[#result + 1] = token.separator
2✔
96
               result[#result + 1] = self.class.packages.inputfilter:createCommand(
4✔
97
                  content.pos,
2✔
98
                  content.col,
2✔
99
                  content.lno,
2✔
100
                  "penalty",
2✔
101
                  { penalty = options.primaryPenalty }
2✔
102
               )
2✔
103
            else
104
               -- Accept breaking after, but tolerate breaking before.
105
               result[#result + 1] = self.class.packages.inputfilter:createCommand(
20✔
106
                  content.pos,
10✔
107
                  content.col,
10✔
108
                  content.lno,
10✔
109
                  "penalty",
10✔
110
                  { penalty = options.secondaryPenalty }
10✔
111
               )
10✔
112
               result[#result + 1] = token.separator
10✔
113
               result[#result + 1] = self.class.packages.inputfilter:createCommand(
20✔
114
                  content.pos,
10✔
115
                  content.col,
10✔
116
                  content.lno,
10✔
117
                  "penalty",
10✔
118
                  { penalty = options.primaryPenalty }
10✔
119
               )
10✔
120
            end
121
         end
122
      end
123
      return result
2✔
124
   end
125

126
   self.commands:register("url", function (options, content)
3✔
127
      self.settings:temporarily(function ()
4✔
128
         local primaryPenalty = self.settings:get("url.linebreak.primaryPenalty")
4✔
129
         local secondaryPenalty = self.settings:get("url.linebreak.secondaryPenalty")
4✔
130
         local worsePenalty = primaryPenalty + secondaryPenalty
2✔
131

132
         if options.language then
2✔
133
            if options.language == "fr" then
×
134
               -- Trick the engine by declaring a "fake"" language that doesn't apply
135
               -- the typographic rules for punctuations
UNCOV
136
               SILE.hyphenator.languages["_fr_noSpacingRules"] = SILE.hyphenator.languages.fr
×
137
               -- Not needed (the engine already defaults to SILE.nodeMakers.unicode if
138
               -- the language is not found):
139
               -- SILE.nodeMakers._fr_noSpacingRules = SILE.nodeMakers.unicode
UNCOV
140
               self.settings:set("document.language", "_fr_noSpacingRules")
×
141
            else
142
               self.settings:set("document.language", options.language)
×
143
            end
144
         else
145
            self.settings:set("document.language", "und")
4✔
146
         end
147

148
         local result = self.class.packages.inputfilter:transformContent(content, urlFilter, {
4✔
149
            primaryPenalty = primaryPenalty,
2✔
150
            secondaryPenalty = secondaryPenalty,
2✔
151
            worsePenalty = worsePenalty,
2✔
152
         })
153
         SILE.call("urlstyle", {}, result)
2✔
154
      end)
155
   end, "Inserts penalties in an URL so it can be broken over multiple lines at appropriate places.")
3✔
156

157
   self.commands:register("urlstyle", function (options, content)
3✔
158
      SILE.call("code", options, content)
1✔
159
   end, "Hook that may be redefined to change the styling of URLs")
2✔
160
end
161

162
package.documentation = [[
163
\begin{document}
164
\use[module=packages.url]
165
This package enhances the typesetting of URLs in two ways.
166
First, it provides the \autodoc:command{\href[src=<url>]{<content>}} command which inserts PDF hyperlinks, \href[src=http://www.sile-typesetter.org/]{like this}.
167

168
The \autodoc:command{\href} command accepts the same \autodoc:parameter{borderwidth}, \autodoc:parameter{bordercolor}, \autodoc:parameter{borderstyle}, and \autodoc:parameter{borderoffset} styling options as the \autodoc:command[check=false]{\pdf:link} command from the \autodoc:package{pdf} package, for instance \href[src=http://www.sile-typesetter.org/, borderwidth=0.4pt, bordercolor=blue, borderstyle=underline]{like this}.
169

170
Nowadays, it is a common practice to have URLs in print articles (whether it is a good practice or not is yet \em{another} topic).
171
Therefore, the package also provides the \autodoc:command{\url} command, which will automatically insert breakpoints into unwieldy URLs like \url{https://github.com/sile-typesetter/sile-typesetter.github.io/tree/master/examples} so that they can be broken up over multiple lines.
172

173
It allows line breaks after the colon, and before or after appropriate segments of an URL (path elements, query parts, fragments, etc.).
174
By default, the \autodoc:command{\url} command ignores the current language, as one would not want hyphenation to occur in URL segments.
175
If you have no other choice, however, you can pass it a \autodoc:parameter{language} option to enforce a language to be applied.
176
Note that if French (\code{fr}) is selected, the special typographic rules applying to punctuations in this language are disabled.
177

178
To typeset a URL and also make it an active hyperlink, use the \autodoc:command{\href} command without the \autodoc:parameter{src} option,
179
but with the URL passed as argument.
180

181
The breaks are controlled by two penalty settings: \autodoc:setting{url.linebreak.primaryPenalty} for preferred breakpoints and, for less acceptable but still tolerable breakpoints, \autodoc:setting{url.linebreak.secondaryPenalty}—its value should logically be higher than the previous one.
182

183
The \autodoc:command{\urlstyle} command hook may be overridden to change the style of URLs.
184
By default, they are typeset as “code”.
185

186
\end{document}
187
]]
1✔
188

189
return package
1✔
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