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

sile-typesetter / sile / 9304060604

30 May 2024 02:07PM UTC coverage: 74.124% (-0.6%) from 74.707%
9304060604

push

github

alerque
style: Reformat Lua with stylua

8104 of 11995 new or added lines in 184 files covered. (67.56%)

15 existing lines in 11 files now uncovered.

12444 of 16788 relevant lines covered (74.12%)

7175.1 hits per line

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

90.99
/packages/pdf/init.lua
1
local base = require("packages.base")
5✔
2

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

6
local pdf
7

8
local function borderColor (color)
9
   if color then
1✔
10
      if color.r then
1✔
11
         return "/C [" .. color.r .. " " .. color.g .. " " .. color.b .. "]"
1✔
12
      end
NEW
13
      if color.c then
×
NEW
14
         return "/C [" .. color.c .. " " .. color.m .. " " .. color.y .. " " .. color.k .. "]"
×
15
      end
NEW
16
      if color.l then
×
NEW
17
         return "/C [" .. color.l .. "]"
×
18
      end
19
   end
NEW
20
   return ""
×
21
end
22

23
local function borderStyle (style, width)
24
   if style == "underline" then
1✔
NEW
25
      return "/BS<</Type/Border/S/U/W " .. width .. ">>"
×
26
   end
27
   if style == "dashed" then
1✔
NEW
28
      return "/BS<</Type/Border/S/D/D[3 2]/W " .. width .. ">>"
×
29
   end
30
   return "/Border[0 0 " .. width .. "]"
1✔
31
end
32

33
local function validate_date (date)
34
   return string.match(date, [[^D:%d+%s*-%s*%d%d%s*'%s*%d%d%s*'?$]]) ~= nil
2✔
35
end
36

37
function package:_init ()
5✔
38
   base._init(self)
5✔
39
   pdf = require("justenoughlibtexpdf")
5✔
40
   if SILE.outputter._name ~= "libtexpdf" then
5✔
NEW
41
      SU.error("pdf package requires libtexpdf backend")
×
42
   end
43
end
44

45
function package:registerCommands ()
5✔
46
   self:registerCommand("pdf:destination", function (options, _)
10✔
47
      local name = SU.required(options, "name", "pdf:destination")
4✔
48
      if type(SILE.outputter._ensureInit) == "function" then
4✔
49
         SILE.outputter:_ensureInit()
4✔
50
      end
51
      SILE.typesetter:pushHbox({
8✔
52
         outputYourself = function (_, typesetter, line)
53
            local state = typesetter.frame.state
4✔
54
            typesetter.frame:advancePageDirection(-line.height)
8✔
55
            local x, y = state.cursorX, state.cursorY
4✔
56
            typesetter.frame:advancePageDirection(line.height)
4✔
57
            local _y = SILE.documentState.paperSize[2] - y
4✔
58
            pdf.destination(name, x:tonumber(), _y:tonumber())
12✔
59
         end,
60
      })
61
   end)
62

63
   self:registerCommand("pdf:bookmark", function (options, _)
10✔
64
      local dest = SU.required(options, "dest", "pdf:bookmark")
4✔
65
      local title = SU.required(options, "title", "pdf:bookmark")
4✔
66
      local level = options.level or 1
4✔
67
      -- Added UTF8 to UTF16-BE conversion
68
      -- For annotations and bookmarks, text strings must be encoded using
69
      -- either PDFDocEncoding or UTF16-BE with a leading byte-order marker.
70
      -- As PDFDocEncoding supports only limited character repertoire for
71
      -- European languages, we use UTF-16BE for internationalization.
72
      local ustr = SU.utf8_to_utf16be_hexencoded(title)
4✔
73
      if type(SILE.outputter._ensureInit) == "function" then
4✔
74
         SILE.outputter:_ensureInit()
4✔
75
      end
76
      SILE.typesetter:pushHbox({
8✔
77
         value = nil,
78
         height = SILE.measurement(0),
8✔
79
         width = SILE.measurement(0),
8✔
80
         depth = SILE.measurement(0),
8✔
81
         outputYourself = function ()
82
            local d = "<</Title<" .. ustr .. ">/A<</S/GoTo/D(" .. dest .. ")>>>>"
4✔
83
            pdf.bookmark(d, level)
4✔
84
         end,
85
      })
86
   end)
87

88
   self:registerCommand("pdf:literal", function (_, content)
10✔
89
      if type(SILE.outputter._ensureInit) == "function" then
6✔
90
         SILE.outputter:_ensureInit()
6✔
91
      end
92
      SILE.typesetter:pushHbox({
12✔
93
         value = nil,
94
         height = SILE.measurement(0),
12✔
95
         width = SILE.measurement(0),
12✔
96
         depth = SILE.measurement(0),
12✔
97
         outputYourself = function (_, _, _)
98
            pdf.add_content(content[1])
6✔
99
         end,
100
      })
101
   end)
102

103
   self:registerCommand("pdf:link", function (options, content)
10✔
104
      local dest = SU.required(options, "dest", "pdf:link")
1✔
105
      local target = options.external and "/Type/Action/S/URI/URI" or "/S/GoTo/D"
1✔
106
      local borderwidth = options.borderwidth and SU.cast("measurement", options.borderwidth):tonumber() or 0
1✔
107
      local bordercolor = borderColor(SILE.color(options.bordercolor or "blue"))
2✔
108
      local borderoffset = SU.cast("measurement", options.borderoffset or "1pt"):tonumber()
2✔
109
      local borderstyle = borderStyle(options.borderstyle, borderwidth)
1✔
110
      local llx, lly
111
      if type(SILE.outputter._ensureInit) == "function" then
1✔
112
         SILE.outputter:_ensureInit()
1✔
113
      end
114
      SILE.typesetter:pushHbox({
2✔
115
         value = nil,
116
         height = SILE.measurement(0),
2✔
117
         width = SILE.measurement(0),
2✔
118
         depth = SILE.measurement(0),
2✔
119
         outputYourself = function (_, typesetter, _)
120
            llx = typesetter.frame.state.cursorX:tonumber()
2✔
121
            lly = (SILE.documentState.paperSize[2] - typesetter.frame.state.cursorY):tonumber()
3✔
122
            pdf.begin_annotation()
1✔
123
         end,
124
      })
125

126
      local hbox, hlist = SILE.typesetter:makeHbox(content) -- hack
1✔
127
      SILE.typesetter:pushHbox(hbox)
1✔
128
      SILE.typesetter:pushHlist(hlist)
1✔
129

130
      SILE.typesetter:pushHbox({
2✔
131
         value = nil,
132
         height = SILE.measurement(0),
2✔
133
         width = SILE.measurement(0),
2✔
134
         depth = SILE.measurement(0),
2✔
135
         outputYourself = function (_, typesetter, _)
NEW
136
            local d = "<</Type/Annot/Subtype/Link"
×
137
               .. borderstyle
1✔
138
               .. bordercolor
1✔
139
               .. "/A<<"
1✔
140
               .. target
1✔
141
               .. "("
1✔
142
               .. dest
1✔
143
               .. ")>>>>"
1✔
144
            local x = typesetter.frame.state.cursorX:tonumber()
1✔
145
            local y = (SILE.documentState.paperSize[2] - typesetter.frame.state.cursorY + hbox.height):tonumber()
3✔
146
            pdf.end_annotation(d, llx, lly - borderoffset, x, y + borderoffset)
1✔
147
         end,
148
      })
149
   end)
150

151
   self:registerCommand("pdf:metadata", function (options, _)
10✔
152
      local key = SU.required(options, "key", "pdf:metadata")
5✔
153
      if options.val ~= nil then
5✔
NEW
154
         SU.deprecated("\\pdf:metadata[…, val=…]", "\\pdf:metadata[…, value=…]", "0.12.0", "0.13.0")
×
155
      end
156
      local value = SU.required(options, "value", "pdf:metadata")
5✔
157

158
      if key == "Trapped" then
5✔
159
         SU.warn("Skipping special metadata key \\Trapped")
1✔
160
         return
1✔
161
      end
162

163
      if key == "ModDate" or key == "CreationDate" then
4✔
164
         if not validate_date(value) then
4✔
165
            SU.warn("Invalid date: " .. value)
1✔
166
            return
1✔
167
         end
168
      else
169
         -- see comment in pdf:bookmark
170
         value = SU.utf8_to_utf16be(value)
4✔
171
      end
172
      if type(SILE.outputter._ensureInit) == "function" then
3✔
173
         SILE.outputter:_ensureInit()
3✔
174
      end
175
      SILE.typesetter:pushHbox({
6✔
176
         value = nil,
177
         height = SILE.measurement(0),
6✔
178
         width = SILE.measurement(0),
6✔
179
         depth = SILE.measurement(0),
6✔
180
         outputYourself = function (_, _, _)
181
            pdf.metadata(key, value)
3✔
182
         end,
183
      })
184
   end)
185
end
186

187
package.documentation = [[
188
\begin{document}
189
The \autodoc:package{pdf} package enables basic support for PDF links and table-of-contents entries.
190
It provides the four commands \autodoc:command{\pdf:destination}, \autodoc:command{\pdf:link}, \autodoc:command{\pdf:bookmark}, and \autodoc:command{\pdf:metadata}.
191

192
The \autodoc:command{\pdf:destination} parameter creates a link target; it expects a parameter called \autodoc:parameter{name} to uniquely identify the target.
193
To create a link to that location in the document, use \autodoc:command{\pdf:link[dest=<name>]{<content>}}.
194

195
The \autodoc:command{\pdf:link} command accepts several options defining its border style: a \autodoc:parameter{borderwidth} length setting the border width (defaults to \code{0}, meaning no border), a \autodoc:parameter{borderstyle} string (can be set to \code{underline} or \code{dashed}, otherwise a solid box), a \autodoc:parameter{bordercolor} color specification for this border (defaults to \code{blue}), and finally a \autodoc:parameter{borderoffset} length for adjusting the border with some vertical space above the content and below the baseline (defaults to \code{1pt}).
196
Note that PDF renderers may vary on how they honor these border styling features on link annotations.
197

198
It also has an \autodoc:parameter{external} option for URL links, which is not intended to be used directly—refer to the \autodoc:package{url} package for more flexibility typesetting external links.
199

200
To set arbitrary key-value metadata, use something like \autodoc:command{\pdf:metadata[key=Author, value=J. Smith]}. The PDF metadata field names are case-sensitive. Common keys include \code{Title}, \code{Author}, \code{Subject}, \code{Keywords}, \code{CreationDate}, and \code{ModDate}.
201
\end{document}
202
]]
5✔
203

204
return package
5✔
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