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

sile-typesetter / sile / 14908152066

08 May 2025 01:49PM UTC coverage: 61.309% (-5.7%) from 67.057%
14908152066

push

github

alerque
chore(registries): Touchup command registry deprecation shims

1 of 2 new or added lines in 2 files covered. (50.0%)

1379 existing lines in 46 files now uncovered.

13556 of 22111 relevant lines covered (61.31%)

11834.23 hits per line

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

0.0
/packages/url/init.lua
UNCOV
1
local base = require("packages.base")
×
2

UNCOV
3
local package = pl.class(base)
×
UNCOV
4
package._name = "url"
×
5

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

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

UNCOV
18
local breakPattern = "[" .. escapeRegExpMinimal(preferBreakBefore .. preferBreakAfter .. alwaysBreakAfter) .. "]"
×
19

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

UNCOV
26
function package:declareSettings ()
×
UNCOV
27
   self.settings:declare({
×
28
      parameter = "url.linebreak.primaryPenalty",
29
      type = "integer",
30
      default = 100,
31
      help = "Penalty for breaking lines in URLs at preferred breakpoints",
32
   })
UNCOV
33
   self.settings:declare({
×
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

UNCOV
41
function package:registerCommands ()
×
UNCOV
42
   self.commands:register("href", function (options, content)
×
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,
51
         }, content)
×
52
      else
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 (_, _)
62
            SILE.call("url", { language = options.language }, content)
×
63
         end)
64
      end
UNCOV
65
   end, "Inserts a PDF hyperlink.")
×
66

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

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

UNCOV
132
         if options.language then
×
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
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
140
               self.settings:set("document.language", "_fr_noSpacingRules")
×
141
            else
142
               self.settings:set("document.language", options.language)
×
143
            end
144
         else
UNCOV
145
            self.settings:set("document.language", "und")
×
146
         end
147

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

UNCOV
157
   self.commands:register("urlstyle", function (options, content)
×
UNCOV
158
      SILE.call("code", options, content)
×
UNCOV
159
   end, "Hook that may be redefined to change the styling of URLs")
×
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}
UNCOV
187
]]
×
188

UNCOV
189
return package
×
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