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

sile-typesetter / sile / 11770252752

11 Nov 2024 01:09AM UTC coverage: 32.853% (-27.5%) from 60.402%
11770252752

Pull #2164

github

web-flow
chore(deps): Bump DeterminateSystems/nix-installer-action from 14 to 15

Bumps [DeterminateSystems/nix-installer-action](https://github.com/determinatesystems/nix-installer-action) from 14 to 15.
- [Release notes](https://github.com/determinatesystems/nix-installer-action/releases)
- [Commits](https://github.com/determinatesystems/nix-installer-action/compare/v14...v15)

---
updated-dependencies:
- dependency-name: DeterminateSystems/nix-installer-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #2164: chore(deps): Bump DeterminateSystems/nix-installer-action from 14 to 15

5855 of 17822 relevant lines covered (32.85%)

2493.73 hits per line

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

75.0
/languages/unicode/init.lua
1
local icu = require("justenoughicu")
5✔
2

3
local chardata = require("char-def")
5✔
4

5
SILE.settings:declare({
5✔
6
   parameter = "languages.fixedNbsp",
7
   type = "boolean",
8
   default = false,
9
   help = "Whether to treat U+00A0 (NO-BREAK SPACE) as a fixed-width space",
10
})
11

12
SILE.nodeMakers.base = pl.class({
10✔
13

14
   _init = function (self, options)
15
      self.contents = {}
794✔
16
      self.options = options
794✔
17
      self.token = ""
794✔
18
      self.lastnode = false
794✔
19
      self.lasttype = false
794✔
20
   end,
21

22
   makeToken = function (self)
23
      if #self.contents > 0 then
1,476✔
24
         coroutine.yield(SILE.shaper:formNnode(self.contents, self.token, self.options))
2,300✔
25
         SU.debug("tokenizer", "Token:", self.token)
1,150✔
26
         self.contents = {}
1,150✔
27
         self.token = ""
1,150✔
28
         self.lastnode = "nnode"
1,150✔
29
      end
30
   end,
31

32
   addToken = function (self, char, item)
33
      self.token = self.token .. char
3,247✔
34
      table.insert(self.contents, item)
3,247✔
35
   end,
36

37
   makeGlue = function (self, item)
38
      if SILE.settings:get("typesetter.obeyspaces") or self.lastnode ~= "glue" then
664✔
39
         SU.debug("tokenizer", "Space node")
332✔
40
         coroutine.yield(SILE.shaper:makeSpaceNode(self.options, item))
664✔
41
      end
42
      self.lastnode = "glue"
332✔
43
      self.lasttype = "sp"
332✔
44
   end,
45

46
   makePenalty = function (self, p)
47
      if self.lastnode ~= "penalty" and self.lastnode ~= "glue" then
323✔
48
         coroutine.yield(SILE.types.node.penalty({ penalty = p or 0 }))
20✔
49
      end
50
      self.lastnode = "penalty"
323✔
51
   end,
52

53
   makeNonBreakingSpace = function (self)
54
      -- Unicode Line Breaking Algorithm (UAX 14) specifies that U+00A0
55
      -- (NO-BREAK SPACE) is expanded or compressed like a normal space.
56
      coroutine.yield(SILE.types.node.kern(SILE.shaper:measureSpace(self.options)))
×
57
      self.lastnode = "glue"
×
58
      self.lasttype = "sp"
×
59
   end,
60

61
   iterator = function (_, _)
62
      SU.error("Abstract function nodemaker:iterator called", true)
×
63
   end,
64

65
   charData = function (_, char)
66
      local cp = SU.codepoint(char)
13,408✔
67
      if not chardata[cp] then
13,408✔
68
         return {}
×
69
      end
70
      return chardata[cp]
13,408✔
71
   end,
72

73
   isActiveNonBreakingSpace = function (self, char)
74
      return self:isNonBreakingSpace(char) and not SILE.settings:get("languages.fixedNbsp")
6,494✔
75
   end,
76

77
   isBreaking = function (self, char)
78
      return self.breakingTypes[self:charData(char).linebreak]
5,778✔
79
   end,
80

81
   isNonBreakingSpace = function (self, char)
82
      local c = self:charData(char)
3,247✔
83
      return c.contextname and c.contextname == "nobreakspace"
3,247✔
84
   end,
85

86
   isPunctuation = function (self, char)
87
      return self.puctuationTypes[self:charData(char).category]
×
88
   end,
89

90
   isSpace = function (self, char)
91
      return self.spaceTypes[self:charData(char).linebreak]
8,746✔
92
   end,
93

94
   isQuote = function (self, char)
95
      return self.quoteTypes[self:charData(char).linebreak]
5,778✔
96
   end,
97

98
   isWord = function (self, char)
99
      return self.wordTypes[self:charData(char).linebreak]
20✔
100
   end,
101
})
5✔
102

103
SILE.nodeMakers.unicode = pl.class(SILE.nodeMakers.base)
10✔
104

105
SILE.nodeMakers.unicode.breakingTypes = { ba = true, zw = true }
5✔
106
SILE.nodeMakers.unicode.puctuationTypes = { po = true }
5✔
107
SILE.nodeMakers.unicode.quoteTypes = {} -- quote linebreak category is ambiguous depending on the language
5✔
108
SILE.nodeMakers.unicode.spaceTypes = { sp = true }
5✔
109
SILE.nodeMakers.unicode.wordTypes = { cm = true }
5✔
110

111
function SILE.nodeMakers.unicode:dealWith (item)
10✔
112
   local char = item.text
2,889✔
113
   local cp = SU.codepoint(char)
2,889✔
114
   local thistype = chardata[cp] and chardata[cp].linebreak
2,889✔
115
   if self:isSpace(item.text) then
5,778✔
116
      self:makeToken()
×
117
      self:makeGlue(item)
×
118
   elseif self:isActiveNonBreakingSpace(item.text) then
5,778✔
119
      self:makeToken()
×
120
      self:makeNonBreakingSpace()
×
121
   elseif self:isBreaking(item.text) then
5,778✔
122
      self:addToken(char, item)
×
123
      self:makeToken()
×
124
      self:makePenalty(0)
×
125
   elseif self:isQuote(item.text) then
5,778✔
126
      self:addToken(char, item)
×
127
      self:makeToken()
×
128
   elseif self.lasttype and (thistype and thistype ~= self.lasttype and not self:isWord(thistype)) then
2,899✔
129
      self:addToken(char, item)
20✔
130
   else
131
      self:letterspace()
2,879✔
132
      self:addToken(char, item)
2,879✔
133
   end
134
   self.lasttype = thistype
2,889✔
135
end
136

137
function SILE.nodeMakers.unicode:handleInitialGlue (items)
10✔
138
   local i = 1
794✔
139
   while i <= #items do
802✔
140
      local item = items[i]
802✔
141
      if self:isSpace(item.text) then
1,604✔
142
         self:makeGlue(item)
16✔
143
      else
144
         break
145
      end
146
      i = i + 1
8✔
147
   end
148
   return i, items
794✔
149
end
150

151
function SILE.nodeMakers.unicode:letterspace ()
10✔
152
   if not SILE.settings:get("document.letterspaceglue") then
5,758✔
153
      return
2,879✔
154
   end
155
   if self.token then
×
156
      self:makeToken()
×
157
   end
158
   if self.lastnode and self.lastnode ~= "glue" then
×
159
      local w = SILE.settings:get("document.letterspaceglue").width
×
160
      SU.debug("tokenizer", "Letter space glue:", w)
×
161
      coroutine.yield(SILE.types.node.kern({ width = w }))
×
162
      self.lastnode = "glue"
×
163
      self.lasttype = "sp"
×
164
   end
165
end
166

167
function SILE.nodeMakers.unicode.isICUBreakHere (_, chunks, item)
10✔
168
   return chunks[1] and (item.index >= chunks[1].index)
3,571✔
169
end
170

171
function SILE.nodeMakers.unicode:handleICUBreak (chunks, item)
10✔
172
   -- The ICU library has told us there is a breakpoint at
173
   -- this index. We need to...
174
   local bp = chunks[1]
682✔
175
   -- ... remove this breakpoint (and any out of order ones)
176
   -- from the ICU breakpoints array so that chunks[1] is
177
   -- the next index point for comparison against the string...
178
   while chunks[1] and item.index >= chunks[1].index do
1,364✔
179
      table.remove(chunks, 1)
1,364✔
180
   end
181
   -- ...decide which kind of breakpoint we have here and
182
   -- handle it appropriately.
183
   if bp.type == "word" then
682✔
184
      self:handleWordBreak(item)
718✔
185
   elseif bp.type == "line" then
323✔
186
      self:handleLineBreak(item, bp.subtype)
323✔
187
   end
188
   return chunks
682✔
189
end
190

191
function SILE.nodeMakers.unicode:handleWordBreak (item)
10✔
192
   self:makeToken()
359✔
193
   if self:isSpace(item.text) then
718✔
194
      -- Spacing word break
195
      self:makeGlue(item)
648✔
196
   elseif self:isActiveNonBreakingSpace(item.text) then
70✔
197
      -- Non-breaking space word break
198
      self:makeNonBreakingSpace()
×
199
   else
200
      -- a word break which isn't a space
201
      self:addToken(item.text, item)
35✔
202
   end
203
end
204

205
function SILE.nodeMakers.unicode:_handleWordBreakRepeatHyphen (item)
10✔
206
   -- According to some language rules, when a break occurs at an explicit hyphen,
207
   -- the hyphen gets repeated at the beginning of the new line
208
   if item.text == "-" then
×
209
      self:addToken(item.text, item)
×
210
      self:makeToken()
×
211
      if self.lastnode ~= "discretionary" then
×
212
         coroutine.yield(SILE.types.node.discretionary({
×
213
            postbreak = SILE.shaper:createNnodes("-", self.options),
214
         }))
215
         self.lastnode = "discretionary"
×
216
      end
217
   else
218
      SILE.nodeMakers.unicode.handleWordBreak(self, item)
×
219
   end
220
end
221

222
function SILE.nodeMakers.unicode:handleLineBreak (item, subtype)
10✔
223
   -- Because we are in charge of paragraphing, we
224
   -- will override space-type line breaks, and treat
225
   -- them just as ordinary word spaces.
226
   if self:isSpace(item.text) or self:isActiveNonBreakingSpace(item.text) then
969✔
227
      self:handleWordBreak(item)
×
228
      return
×
229
   end
230
   -- But explicit line breaks we will turn into
231
   -- soft and hard breaks.
232
   self:makeToken()
323✔
233
   self:makePenalty(subtype == "soft" and 0 or -1000)
323✔
234
   local char = item.text
323✔
235
   self:addToken(char, item)
323✔
236
   local cp = SU.codepoint(char)
323✔
237
   self.lasttype = chardata[cp] and chardata[cp].linebreak
323✔
238
end
239

240
function SILE.nodeMakers.unicode:_handleLineBreakRepeatHyphen (item, subtype)
10✔
241
   if self.lastnode == "discretionary" then
×
242
      -- Initial word boundary after a discretionary:
243
      -- Bypass it and just deal with the token.
244
      self:dealWith(item)
×
245
   else
246
      SILE.nodeMakers.unicode.handleLineBreak(self, item, subtype)
×
247
   end
248
end
249

250
function SILE.nodeMakers.unicode:iterator (items)
10✔
251
   local fulltext = ""
794✔
252
   for i = 1, #items do
4,373✔
253
      fulltext = fulltext .. items[i].text
3,579✔
254
   end
255
   local chunks = { icu.breakpoints(fulltext, self.options.language) }
794✔
256
   table.remove(chunks, 1)
794✔
257
   return coroutine.wrap(function ()
794✔
258
      local i
259
      i, self.items = self:handleInitialGlue(items)
1,588✔
260
      for j = i, #items do
4,365✔
261
         self.i = j
3,571✔
262
         self.item = self.items[self.i]
3,571✔
263
         if self:isICUBreakHere(chunks, self.item) then
7,142✔
264
            chunks = self:handleICUBreak(chunks, self.item)
1,364✔
265
         else
266
            self:dealWith(self.item)
2,889✔
267
         end
268
      end
269
      self:makeToken()
794✔
270
   end)
271
end
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