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

sile-typesetter / sile / 10881107806

16 Sep 2024 09:29AM UTC coverage: 61.663% (-7.2%) from 68.912%
10881107806

push

github

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

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

10751 of 17435 relevant lines covered (61.66%)

2338.25 hits per line

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

68.97
/languages/ja.lua
1
-- "jlreq" refers to http://www.w3.org/TR/jlreq/
2
-- "JIS" refers to JIS X 4051
3

4
local hiragana = function (c)
5
   return c > 0x3040 and c <= 0x309f
16✔
6
end
7
local katakana = function (c)
8
   return c > 0x30a0 and c <= 0x30ff
16✔
9
end
10
local kanji = function (c)
11
   return c >= 0x4e00 and c <= 0x9fcc
16✔
12
end
13

14
local classes = { -- from jlreq
1✔
15
   [0x2018] = 1,
16
   [0x201C] = 1,
17
   [0x0028] = 1,
18
   [0x3014] = 1,
19
   [0x005B] = 1,
20
   [0x007B] = 1,
21
   [0x3008] = 1,
22
   [0x300A] = 1,
23
   [0x300C] = 1,
24
   [0x300E] = 1,
25
   [0x3010] = 1,
26
   [0x2985] = 1,
27
   [0x3018] = 1,
28
   [0x3016] = 1,
29
   [0x00AB] = 1,
30
   [0x301D] = 1,
31
   [0xFF08] = 1, -- see note 1 of appendix A
32
   [0x2019] = 2,
33
   [0x201D] = 2,
34
   [0x0029] = 2,
35
   [0x3015] = 2,
36
   [0x005D] = 2,
37
   [0x007D] = 2,
38
   [0x3009] = 2,
39
   [0x300B] = 2,
40
   [0x300D] = 2,
41
   [0x300F] = 2,
42
   [0x3011] = 2,
43
   [0x2986] = 2,
44
   [0x3019] = 2,
45
   [0x3017] = 2,
46
   [0x00BB] = 2,
47
   [0x301F] = 2,
48
   [0xFF09] = 2, -- see note 1 of appendix A
49
   [0x2010] = 3,
50
   [0x301C] = 3,
51
   [0x30A0] = 3,
52
   [0x2013] = 3,
53
   [0x0021] = 4,
54
   [0x003F] = 4,
55
   [0x203C] = 4,
56
   [0x2047] = 4,
57
   [0x2048] = 4,
58
   [0x2049] = 4,
59
   [0x30FB] = 5,
60
   [0x003A] = 5,
61
   [0x003B] = 5,
62
   [0x3002] = 6,
63
   [0x002E] = 6,
64
   [0x3001] = 7,
65
   [0x002C] = 7,
66
   [0x2014] = 8,
67
   [0x2026] = 8,
68
   [0x2025] = 8,
69
   [0x3033] = 8,
70
   [0x3034] = 8,
71
   [0x3035] = 8,
72
   [0x30FD] = 9,
73
   [0x30FE] = 9,
74
   [0x309D] = 9,
75
   [0x309E] = 9,
76
   [0x3005] = 9,
77
   [0x303B] = 9,
78
   [0x30FC] = 10,
79
   [0x3041] = 11,
80
   [0x3043] = 11,
81
   [0x3045] = 11,
82
   [0x3047] = 11,
83
   [0x3049] = 11,
84
   [0x30A1] = 11,
85
   [0x30A3] = 11,
86
   [0x30A5] = 11,
87
   [0x30A7] = 11,
88
   [0x30A9] = 11,
89
   [0x3063] = 11,
90
   [0x3083] = 11,
91
   [0x3085] = 11,
92
   [0x3087] = 11,
93
   [0x308E] = 11,
94
   [0x3095] = 11,
95
   [0x3096] = 11,
96
   [0x30C3] = 11,
97
   [0x30E3] = 11,
98
   [0x30E5] = 11,
99
   [0x30E7] = 11,
100
   [0x30EE] = 11,
101
   [0x30F5] = 11,
102
   [0x30F6] = 11,
103
   [0x31F0] = 11,
104
   [0x31F1] = 11,
105
   [0x31F2] = 11,
106
   [0x31F3] = 11,
107
   [0x31F4] = 11,
108
   [0x31F5] = 11,
109
   [0x31F6] = 11,
110
   [0x31F7] = 11,
111
   [0x31F8] = 11,
112
   [0x31F9] = 11,
113
   [0x31FA] = 11,
114
   [0x31FB] = 11,
115
   [0x31FC] = 11,
116
   [0x31FD] = 11,
117
   [0x31FE] = 11,
118
   [0x31FF] = 11,
119
   [0x00A5] = 12,
120
   [0x0024] = 12,
121
   [0x00A3] = 12,
122
   [0x0023] = 12,
123
   [0x20AC] = 12,
124
   [0x2116] = 12,
125
   [0x00B0] = 13,
126
   [0x2032] = 13,
127
   [0x2033] = 13,
128
   [0x2103] = 13,
129
   [0x00A2] = 13,
130
   [0x0025] = 13,
131
   [0x2030] = 13,
132
   [0x33CB] = 13,
133
   [0x2113] = 13,
134
   [0x3303] = 13,
135
   [0x330D] = 13,
136
   [0x3314] = 13,
137
   [0x3318] = 13,
138
   [0x3322] = 13,
139
   [0x3323] = 13,
140
   [0x3326] = 13,
141
   [0x3327] = 13,
142
   [0x332B] = 13,
143
   [0x3336] = 13,
144
   [0x333B] = 13,
145
   [0x3349] = 13,
146
   [0x334A] = 13,
147
   [0x334D] = 13,
148
   [0x3351] = 13,
149
   [0x3357] = 13,
150
   [0x338E] = 13,
151
   [0x338F] = 13,
152
   [0x339C] = 13,
153
   [0x339D] = 13,
154
   [0x339E] = 13,
155
   [0x33A1] = 13,
156
   [0x33C4] = 13,
157
   [0x3000] = 14,
158
}
159

160
local jisClass = function (c)
161
   if c == -1 then
20✔
162
      return -1
4✔
163
   end
164
   if classes[c] then
16✔
165
      return classes[c]
×
166
   end
167
   if hiragana(c) then
32✔
168
      return 15
×
169
   end
170
   if katakana(c) then
32✔
171
      return 16
×
172
   end
173
   if kanji(c) then
32✔
174
      return 19
16✔
175
   end -- Other things are also 19
176
   return 27 -- this is lazy
×
177
end
178

179
-- This roughly implements the kinsoku shori given in Appendix C of jlreq
180
local badBeforeClasses = { [1] = true, [12] = true, [28] = true }
1✔
181
local badAfterClasses = {}
1✔
182
for _, v in ipairs({ 2, 3, 4, 5, 6, 7, 9, 10, 11, 20, 29 }) do
12✔
183
   badAfterClasses[v] = true
11✔
184
end
185

186
local function breakAllowed (before, after)
187
   local bc = jisClass(before)
2✔
188
   local ac = jisClass(after)
2✔
189
   if badBeforeClasses[bc] then
2✔
190
      return false
×
191
   end
192
   if badAfterClasses[ac] then
2✔
193
      return false
×
194
   end
195
   if bc == 8 and ac == 8 then
2✔
196
      if before == after then
×
197
         return false
×
198
      else
199
         return true
×
200
      end
201
   end
202
   -- The following rule is not in jlreq but it stops the algorithm from breaking
203
   -- up Latin words!
204
   if bc == 27 and ac == 27 then
2✔
205
      return false
×
206
   end
207
   return true
2✔
208
end
209

210
local function intercharacterspace (before, after)
211
   local bc = jisClass(before)
2✔
212
   local ac = jisClass(after)
2✔
213
   -- This rule is not in jlreq but it stops situations like 1:2 getting munched
214
   if (bc == 5 and ac == 27) or (bc == 27 and ac == 5) then
2✔
215
      return 0
×
216
   end
217

218
   -- jlreq expects yakumono to contain no following space, so recommends half
219
   -- a space afterwards. However, in real world fonts, yakumono occupies a full
220
   -- zenkaku width with trailing space built into the glyph. So we do not add
221
   -- space there. Instead, where no space is stipulated, we add negative space
222
   -- to counteract the trailing space in the glyph.
223
   if ac == 5 then
2✔
224
      return "-0.25zw"
×
225
   end
226
   if bc == 5 then
2✔
227
      return "-0.25zw"
×
228
   end
229
   if bc == 7 and ac == 1 then
2✔
230
      return "-0.5zw"
×
231
   end
232
   if bc == 2 and ac == 1 then
2✔
233
      return "-0.5zw"
×
234
   end
235
   if bc == -1 and ac == 1 then
2✔
236
      return "-0.5zw"
×
237
   end
238
   if bc == 6 or bc == 7 then
2✔
239
      if ac == 2 or ac == 6 or ac == 7 then
×
240
         return "-0.25zw"
×
241
      end
242
      return 0
×
243
   end
244
   if (bc == 9 or bc == 10 or bc == 11 or bc == 15 or bc == 16 or bc == 19) and (ac == 21 or ac == 24 or ac == 25) then
2✔
245
      return "0.25zw"
×
246
   end
247

248
   return 0
2✔
249
end
250

251
local function stretchability (before, after)
252
   local bc = jisClass(before)
2✔
253
   local ac = jisClass(after)
2✔
254
   -- somewhat simplified from table 6 of jlreq
255
   if ac == 1 then
2✔
256
      return "0.25zw"
×
257
   end
258
   if ac < 8 then
2✔
259
      return 0
×
260
   end
261
   if bc == 4 and (ac == 21 or ac == 24 or ac == 25 or ac == 27) then
2✔
262
      return "0.5zw"
×
263
   end
264
   if bc < 8 then
2✔
265
      return 0
1✔
266
   end
267
   return "0.25zw" -- somewhat simplified
1✔
268
end
269

270
local function shrinkability (before, after)
271
   local bc = jisClass(before)
2✔
272
   local ac = jisClass(after)
2✔
273
   -- This rule is not in jlreq but it stops situations like 1:2 getting munched
274
   if (bc == 5 and ac == 27) or (bc == 27 and ac == 5) then
2✔
275
      return 0
×
276
   end
277
   -- somewhat simplified from table 5 of jlreq
278
   if ac == 1 then
2✔
279
      return "0.5zw"
×
280
   end
281
   if ac == 5 then
2✔
282
      return "0.25zw"
×
283
   end
284
   if bc == 5 then
2✔
285
      return "0.25zw"
×
286
   end
287
   if bc == 7 then
2✔
288
      return "0.5zw"
×
289
   end
290
   return 0
2✔
291
end
292

293
-- local okbreak = SILE.types.node.penalty(0)
294

295
SILE.nodeMakers.ja = pl.class(SILE.nodeMakers.base)
2✔
296

297
function SILE.nodeMakers.ja:iterator (items)
2✔
298
   local options = self.options
1✔
299
   return coroutine.wrap(function ()
1✔
300
      local db
301
      local lastcp = -1
1✔
302
      local lastchar = ""
1✔
303
      local space = "%s" -- XXX
1✔
304
      for i = 1, #items do
4✔
305
         local item = items[i]
3✔
306
         local uchar = items[i].text
3✔
307
         local thiscp = SU.codepoint(uchar)
3✔
308
         db = lastchar .. "|" .. uchar
3✔
309
         if string.match(uchar, space) then
3✔
310
            db = db .. " S"
1✔
311
            coroutine.yield(SILE.shaper:makeSpaceNode(options, item))
3✔
312
         else
313
            local length = SILE.types
2✔
314
               .length(intercharacterspace(lastcp, thiscp), stretchability(lastcp, thiscp), shrinkability(lastcp, thiscp))
8✔
315
               :absolute()
2✔
316
            if breakAllowed(lastcp, thiscp) then
4✔
317
               db = db .. " G " .. tostring(length)
4✔
318
               coroutine.yield(SILE.types.node.glue(length))
6✔
319
            elseif length.length ~= 0 or length.stretch ~= 0 or length.shrink ~= 0 then
×
320
               db = db .. " K " .. tostring(length)
×
321
               coroutine.yield(SILE.types.node.kern(length))
×
322
            else
323
               db = db .. " N"
×
324
            end
325
            if jisClass(thiscp) == 5 or jisClass(thiscp) == 6 then
6✔
326
               local node = SILE.shaper:formNnode({ item }, uchar, options)
×
327
               node.hangable = true
×
328
               coroutine.yield(node)
×
329
            else
330
               coroutine.yield(SILE.shaper:formNnode({ item }, uchar, options))
4✔
331
            end
332
         end
333
         lastcp = thiscp
3✔
334
         lastchar = uchar
3✔
335
         SU.debug("ja", db)
3✔
336
      end
337
   end)
338
end
339

340
return {
1✔
341
   init = function ()
342
      SILE.hyphenator.languages.ja = { patterns = {} }
1✔
343

344
      SILE.registerCommand("book:chapter:post:ja", function (_, _)
2✔
345
         SILE.call("medskip")
×
346
      end, nil, nil, true)
1✔
347
   end,
348
}
1✔
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