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

sile-typesetter / sile / 6934957716

20 Nov 2023 07:35PM UTC coverage: 57.468% (-3.2%) from 60.703%
6934957716

push

github

web-flow
Merge c91d9a7d4 into 34e2e5335

60 of 79 new or added lines in 1 file covered. (75.95%)

717 existing lines in 27 files now uncovered.

8957 of 15586 relevant lines covered (57.47%)

5715.38 hits per line

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

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

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

6
local pdf
7

8
local function borderColor (color)
UNCOV
9
  if color then
×
UNCOV
10
    if color.r then return "/C [" .. color.r .. " " .. color.g .. " " .. color.b .. "]" end
×
11
    if color.c then return "/C [" .. color.c .. " " .. color.m .. " " .. color.y .. " " .. color.k .. "]" end
×
12
    if color.l then return "/C [" .. color.l .. "]" end
×
13
  end
14
  return ""
×
15
end
16

17
local function borderStyle (style, width)
UNCOV
18
  if style == "underline" then return "/BS<</Type/Border/S/U/W " .. width .. ">>" end
×
UNCOV
19
  if style == "dashed" then return "/BS<</Type/Border/S/D/D[3 2]/W " .. width .. ">>" end
×
UNCOV
20
  return "/Border[0 0 " .. width .. "]"
×
21
end
22

23
local function validate_date (date)
24
  return string.match(date, [[^D:%d+%s*-%s*%d%d%s*'%s*%d%d%s*'?$]]) ~= nil
×
25
end
26

UNCOV
27
function package:_init ()
×
UNCOV
28
  base._init(self)
×
UNCOV
29
  pdf = require("justenoughlibtexpdf")
×
UNCOV
30
  if SILE.outputter._name ~= "libtexpdf" then
×
31
    SU.error("pdf package requires libtexpdf backend")
×
32
  end
33
end
34

UNCOV
35
function package:registerCommands ()
×
36

UNCOV
37
  self:registerCommand("pdf:destination", function (options, _)
×
UNCOV
38
    local name = SU.required(options, "name", "pdf:destination")
×
UNCOV
39
    if type(SILE.outputter._ensureInit) == "function" then
×
UNCOV
40
      SILE.outputter:_ensureInit()
×
41
    end
UNCOV
42
    SILE.typesetter:pushHbox({
×
43
      outputYourself = function (_, typesetter, line)
UNCOV
44
        local state = typesetter.frame.state
×
UNCOV
45
        typesetter.frame:advancePageDirection(-line.height)
×
UNCOV
46
        local x, y = state.cursorX, state.cursorY
×
UNCOV
47
        typesetter.frame:advancePageDirection(line.height)
×
UNCOV
48
        local _y = SILE.documentState.paperSize[2] - y
×
UNCOV
49
        pdf.destination(name, x:tonumber(), _y:tonumber())
×
50
      end
51
    })
52
  end)
53

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

UNCOV
79
  self:registerCommand("pdf:literal", function (_, content)
×
UNCOV
80
    if type(SILE.outputter._ensureInit) == "function" then
×
UNCOV
81
      SILE.outputter:_ensureInit()
×
82
    end
UNCOV
83
    SILE.typesetter:pushHbox({
×
84
      value = nil,
85
      height = SILE.measurement(0),
86
      width = SILE.measurement(0),
87
      depth = SILE.measurement(0),
88
      outputYourself = function (_, _, _)
UNCOV
89
        pdf.add_content(content[1])
×
90
      end
91
    })
92
  end)
93

UNCOV
94
  self:registerCommand("pdf:link", function (options, content)
×
UNCOV
95
    local dest = SU.required(options, "dest", "pdf:link")
×
UNCOV
96
    local target = options.external and "/Type/Action/S/URI/URI" or "/S/GoTo/D"
×
UNCOV
97
    local borderwidth = options.borderwidth and SU.cast("measurement", options.borderwidth):tonumber() or 0
×
UNCOV
98
    local bordercolor = borderColor(SILE.color(options.bordercolor or "blue"))
×
UNCOV
99
    local borderoffset = SU.cast("measurement", options.borderoffset or "1pt"):tonumber()
×
UNCOV
100
    local borderstyle = borderStyle(options.borderstyle, borderwidth)
×
101
    local llx, lly
UNCOV
102
    if type(SILE.outputter._ensureInit) == "function" then
×
UNCOV
103
      SILE.outputter:_ensureInit()
×
104
    end
UNCOV
105
    SILE.typesetter:pushHbox({
×
106
      value = nil,
107
      height = SILE.measurement(0),
108
      width = SILE.measurement(0),
109
      depth = SILE.measurement(0),
110
      outputYourself = function (_, typesetter, _)
UNCOV
111
        llx = typesetter.frame.state.cursorX:tonumber()
×
UNCOV
112
        lly = (SILE.documentState.paperSize[2] - typesetter.frame.state.cursorY):tonumber()
×
UNCOV
113
        pdf.begin_annotation()
×
114
      end
115
    })
116

UNCOV
117
    local hbox, hlist = SILE.typesetter:makeHbox(content) -- hack
×
UNCOV
118
    SILE.typesetter:pushHbox(hbox)
×
UNCOV
119
    SILE.typesetter:pushHlist(hlist)
×
120

UNCOV
121
    SILE.typesetter:pushHbox({
×
122
      value = nil,
123
      height = SILE.measurement(0),
124
      width = SILE.measurement(0),
125
      depth = SILE.measurement(0),
126
      outputYourself = function (_, typesetter, _)
UNCOV
127
        local d = "<</Type/Annot/Subtype/Link" .. borderstyle .. bordercolor .. "/A<<" .. target .. "(" .. dest .. ")>>>>"
×
UNCOV
128
        local x = typesetter.frame.state.cursorX:tonumber()
×
UNCOV
129
        local y = (SILE.documentState.paperSize[2] - typesetter.frame.state.cursorY + hbox.height):tonumber()
×
UNCOV
130
        pdf.end_annotation(d, llx , lly - borderoffset, x, y + borderoffset)
×
131
      end
132
    })
133
  end)
134

UNCOV
135
  self:registerCommand("pdf:metadata", function (options, _)
×
136
    local key = SU.required(options, "key", "pdf:metadata")
×
137
    if options.val ~= nil then
×
138
      SU.deprecated("\\pdf:metadata[…, val=…]", "\\pdf:metadata[…, value=…]", "0.12.0", "0.13.0")
×
139
    end
140
    local value = SU.required(options, "value", "pdf:metadata")
×
141

142
    if key == "Trapped" then
×
143
      SU.warn("Skipping special metadata key \\Trapped")
×
144
      return
×
145
    end
146

147
    if key == "ModDate" or key == "CreationDate" then
×
148
      if not validate_date(value) then
×
149
        SU.warn("Invalid date: " .. value)
×
150
        return
×
151
      end
152
    else
153
      -- see comment in pdf:bookmark
154
      value = SU.utf8_to_utf16be(value)
×
155
    end
156
    if type(SILE.outputter._ensureInit) == "function" then
×
157
      SILE.outputter:_ensureInit()
×
158
    end
159
    SILE.typesetter:pushHbox({
×
160
      value = nil,
161
      height = SILE.measurement(0),
162
      width = SILE.measurement(0),
163
      depth = SILE.measurement(0),
164
      outputYourself = function (_, _, _)
165
        pdf.metadata(key, value)
×
166
      end
167
    })
168
  end)
169

170
end
171

172
package.documentation = [[
173
\begin{document}
174
The \autodoc:package{pdf} package enables basic support for PDF links and table-of-contents entries.
175
It provides the four commands \autodoc:command{\pdf:destination}, \autodoc:command{\pdf:link}, \autodoc:command{\pdf:bookmark}, and \autodoc:command{\pdf:metadata}.
176

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

180
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}).
181
Note that PDF renderers may vary on how they honor these border styling features on link annotations.
182

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

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