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

sile-typesetter / sile / 9428435077

08 Jun 2024 11:35AM UTC coverage: 64.56% (-9.9%) from 74.46%
9428435077

push

github

web-flow
Merge pull request #2047 from alerque/end-pars

23 of 46 new or added lines in 5 files covered. (50.0%)

1684 existing lines in 60 files now uncovered.

11145 of 17263 relevant lines covered (64.56%)

4562.45 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("verbatim")
×
UNCOV
23
   self:loadPackage("inputfilter")
×
UNCOV
24
   self:loadPackage("pdf")
×
25
end
26

UNCOV
27
function package.declareSettings (_)
×
UNCOV
28
   SILE.settings:declare({
×
29
      parameter = "url.linebreak.primaryPenalty",
30
      type = "integer",
31
      default = 100,
32
      help = "Penalty for breaking lines in URLs at preferred breakpoints",
33
   })
34

UNCOV
35
   SILE.settings:declare({
×
36
      parameter = "url.linebreak.secondaryPenalty",
37
      type = "integer",
38
      default = 200,
39
      help = "Penalty for breaking lines in URLs at tolerable breakpoints (should be higher than url.linebreak.primaryPenalty)",
40
   })
41
end
42

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

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

UNCOV
128
   self:registerCommand("url", function (options, content)
×
UNCOV
129
      SILE.settings:temporarily(function ()
×
UNCOV
130
         local primaryPenalty = SILE.settings:get("url.linebreak.primaryPenalty")
×
UNCOV
131
         local secondaryPenalty = SILE.settings:get("url.linebreak.secondaryPenalty")
×
UNCOV
132
         local worsePenalty = primaryPenalty + secondaryPenalty
×
133

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

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

UNCOV
160
   self:registerCommand("urlstyle", function (options, content)
×
UNCOV
161
      SILE.call("code", options, content)
×
UNCOV
162
   end, "Hook that may be redefined to change the styling of URLs")
×
163
end
164

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

171
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}.
172

173
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).
174
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.
175

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

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

184
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.
185

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

189
\end{document}
UNCOV
190
]]
×
191

UNCOV
192
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