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

sile-typesetter / sile / 8288578143

14 Mar 2024 09:39PM UTC coverage: 64.155% (-10.6%) from 74.718%
8288578143

Pull #1904

github

alerque
chore(core): Fixup ec6ed657 which didn't shim old pack styles properly
Pull Request #1904: Merge develop into master (commit to next release being breaking)

1648 of 2421 new or added lines in 107 files covered. (68.07%)

1843 existing lines in 77 files now uncovered.

10515 of 16390 relevant lines covered (64.15%)

3306.56 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")
×
NEW
24
  self:loadPackage("pdf")
×
25
end
26

UNCOV
27
function package.declareSettings (_)
×
28

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

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

43
end
44

UNCOV
45
function package:registerCommands ()
×
46

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

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

UNCOV
110
  self:registerCommand("url", function (options, content)
×
UNCOV
111
    SILE.settings:temporarily(function ()
×
UNCOV
112
      local primaryPenalty = SILE.settings:get("url.linebreak.primaryPenalty")
×
UNCOV
113
      local secondaryPenalty = SILE.settings:get("url.linebreak.secondaryPenalty")
×
UNCOV
114
      local worsePenalty = primaryPenalty + secondaryPenalty
×
115

UNCOV
116
      if options.language then
×
117
        SILE.languageSupport.loadLanguage(options.language)
×
118
        if options.language == "fr" then
×
119
          -- Trick the engine by declaring a "fake"" language that doesn't apply
120
          -- the typographic rules for punctuations
121
          SILE.hyphenator.languages["_fr_noSpacingRules"] = SILE.hyphenator.languages.fr
×
122
          -- Not needed (the engine already defaults to SILE.nodeMakers.unicode if
123
          -- the language is not found):
124
          -- SILE.nodeMakers._fr_noSpacingRules = SILE.nodeMakers.unicode
125
          SILE.settings:set("document.language", "_fr_noSpacingRules")
×
126
        else
127
          SILE.settings:set("document.language", options.language)
×
128
        end
129
      else
UNCOV
130
        SILE.settings:set("document.language", 'und')
×
131
      end
132

UNCOV
133
      local result = self.class.packages.inputfilter:transformContent(content, urlFilter, {
×
134
        primaryPenalty = primaryPenalty,
135
        secondaryPenalty = secondaryPenalty,
UNCOV
136
        worsePenalty = worsePenalty
×
137
      })
UNCOV
138
      SILE.call("urlstyle", {}, result)
×
139
    end)
UNCOV
140
  end, "Inserts penalties in an URL so it can be broken over multiple lines at appropriate places.")
×
141

UNCOV
142
  self:registerCommand("urlstyle", function (options, content)
×
UNCOV
143
    SILE.call("code", options, content)
×
UNCOV
144
  end, "Hook that may be redefined to change the styling of URLs")
×
145

146
end
147

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

154
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}.
155

156
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).
157
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.
158

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

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

167
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.
168

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

172
\end{document}
UNCOV
173
]]
×
174

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