• 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

0.0
/packages/math/typesetter.lua
1
-- Interpret a MathML or TeX-like AST, typeset it and add it to the output.
2
local b = require("packages.math.base-elements")
×
3
local syms = require("packages.math.unicode-symbols")
×
4
local mathvariants = require("packages.math.unicode-mathvariants")
×
5
local mathVariantToScriptType, scriptType = mathvariants.mathVariantToScriptType, mathvariants.scriptType
×
6

7
-- Shorthands for atom types, used in the `atom` command option
8
local atomTypeShort = {
×
9
   ord = b.atomType.ordinary,
10
   big = b.atomType.bigOperator,
11
   bin = b.atomType.binaryOperator,
12
   rel = b.atomType.relationalOperator,
13
   open = b.atomType.openingSymbol,
14
   close = b.atomType.closeSymbol,
15
   punct = b.atomType.punctuationSymbol,
16
   inner = b.atomType.inner,
17
   over = b.atomType.overSymbol,
18
   under = b.atomType.underSymbol,
19
   accent = b.atomType.accentSymbol,
20
   radical = b.atomType.radicalSymbol,
21
   vcenter = b.atomType.vcenter,
22
}
23

24
local ConvertMathML
25

26
local function convertChildren (tree)
27
   local mboxes = {}
×
28
   for _, n in ipairs(tree) do
×
29
      local box = ConvertMathML(nil, n)
×
30
      if box then
×
31
         table.insert(mboxes, box)
×
32
      end
33
   end
34
   return mboxes
×
35
end
36

37
local function convertFirstChild (tree)
38
   -- We need to loop until the first non-nil box is found, because
39
   -- we may have blank lines in the tree.
40
   for _, n in ipairs(tree) do
×
41
      local box = ConvertMathML(nil, n)
×
42
      if box then
×
43
         return box
×
44
      end
45
   end
46
end
47

48
-- convert MathML into mbox
49
function ConvertMathML (_, content)
×
50
   if content == nil or content.command == nil then
×
51
      return nil
×
52
   end
53
   if content.command == "math" or content.command == "mathml" then -- toplevel
×
54
      return b.stackbox("H", convertChildren(content))
×
55
   elseif content.command == "mrow" then
×
56
      return b.stackbox("H", convertChildren(content))
×
57
   elseif content.command == "mphantom" then
×
58
      -- MathML's standard mphantom corresponds to TeX's \phantom only.
59
      -- Let's support a special attribute "h" or "v" for TeX-like \hphantom or \vphantom.
60
      local special = content.options.special
×
61
      return b.phantom(convertChildren(content), special)
×
62
   elseif content.command == "mi" then
×
63
      local script = content.options.mathvariant and mathVariantToScriptType(content.options.mathvariant)
×
64
      local text = content[1]
×
65
      if type(text) ~= "string" then
×
66
         SU.error("mi command contains content which is not text")
×
67
      end
68
      script = script or (luautf8.len(text) == 1 and scriptType.italic or scriptType.upright)
×
69
      return b.text("identifier", {}, script, text)
×
70
   elseif content.command == "mo" then
×
71
      local script = content.options.mathvariant and mathVariantToScriptType(content.options.mathvariant)
×
72
         or scriptType.upright
×
73
      local text = content[1]
×
74
      local attributes = {}
×
75
      -- Attributes from the (default) oerator table
76
      if syms.symbolDefaults[text] then
×
77
         for attribute, value in pairs(syms.symbolDefaults[text]) do
×
78
            attributes[attribute] = value
×
79
         end
80
      end
81
      -- Overwrite with attributes from the element
82
      for attribute, value in pairs(content.options) do
×
83
         attributes[attribute] = value
×
84
      end
85
      if content.options.atom then
×
86
         if not atomTypeShort[content.options.atom] then
×
87
            SU.error("Unknown atom type " .. content.options.atom)
×
88
         else
89
            attributes.atom = atomTypeShort[content.options.atom]
×
90
         end
91
      end
92
      if type(text) ~= "string" then
×
93
         SU.error("mo command contains content which is not text")
×
94
      end
95
      return b.text("operator", attributes, script, text)
×
96
   elseif content.command == "mn" then
×
97
      local script = content.options.mathvariant and mathVariantToScriptType(content.options.mathvariant)
×
98
         or scriptType.upright
×
99
      local text = content[1]
×
100
      if type(text) ~= "string" then
×
101
         SU.error("mn command contains content which is not text")
×
102
      end
103
      if string.sub(text, 1, 1) == "-" then
×
104
         text = "−" .. string.sub(text, 2)
×
105
      end
106
      return b.text("number", {}, script, text)
×
107
   elseif content.command == "mspace" then
×
108
      return b.space(content.options.width, content.options.height, content.options.depth)
×
109
   elseif content.command == "msub" then
×
110
      local children = convertChildren(content)
×
111
      if #children ~= 2 then
×
112
         SU.error("Wrong number of children in msub")
×
113
      end
114
      return b.newSubscript({ base = children[1], sub = children[2] })
×
115
   elseif content.command == "msup" then
×
116
      local children = convertChildren(content)
×
117
      if #children ~= 2 then
×
118
         SU.error("Wrong number of children in msup")
×
119
      end
120
      return b.newSubscript({ base = children[1], sup = children[2] })
×
121
   elseif content.command == "msubsup" then
×
122
      local children = convertChildren(content)
×
123
      if #children ~= 3 then
×
124
         SU.error("Wrong number of children in msubsup")
×
125
      end
126
      return b.newSubscript({ base = children[1], sub = children[2], sup = children[3] })
×
127
   elseif content.command == "munder" then
×
128
      local children = convertChildren(content)
×
129
      if #children ~= 2 then
×
130
         SU.error("Wrong number of children in munder")
×
131
      end
132
      return b.newUnderOver({ base = children[1], sub = children[2] })
×
133
   elseif content.command == "mover" then
×
134
      local children = convertChildren(content)
×
135
      if #children ~= 2 then
×
136
         SU.error("Wrong number of children in mover")
×
137
      end
138
      return b.newUnderOver({ base = children[1], sup = children[2] })
×
139
   elseif content.command == "munderover" then
×
140
      local children = convertChildren(content)
×
141
      if #children ~= 3 then
×
142
         SU.error("Wrong number of children in munderover")
×
143
      end
144
      return b.newUnderOver({ base = children[1], sub = children[2], sup = children[3] })
×
145
   elseif content.command == "mfrac" then
×
146
      local children = convertChildren(content)
×
147
      if #children ~= 2 then
×
148
         SU.error("Wrong number of children in mfrac: " .. #children)
×
149
      end
150
      return b.fraction(content.options, children[1], children[2])
×
151
   elseif content.command == "msqrt" then
×
152
      local children = convertChildren(content)
×
153
      -- "The <msqrt> element generates an anonymous <mrow> box called the msqrt base
154
      return b.sqrt(b.stackbox("H", children))
×
155
   elseif content.command == "mroot" then
×
156
      local children = convertChildren(content)
×
157
      return b.sqrt(children[1], children[2])
×
158
   elseif content.command == "mtable" or content.command == "table" then
×
159
      local children = convertChildren(content)
×
160
      return b.table(children, content.options)
×
161
   elseif content.command == "mtr" then
×
162
      return b.mtr(convertChildren(content))
×
163
   elseif content.command == "mtd" then
×
164
      return b.stackbox("H", convertChildren(content))
×
165
   elseif content.command == "mtext" or content.command == "ms" then
×
166
      if #content > 1 then
×
167
         SU.error("Wrong number of children in " .. content.command .. ": " .. #content)
×
168
      end
169
      local text = content[1] or "" -- empty mtext is allowed, and found in examples...
×
170
      if type(text) ~= "string" then
×
171
         SU.error(content.command .. " command contains content which is not text")
×
172
      end
173
      -- MathML Core 3.2.1.1 Layout of <mtext> has some wording about forced line breaks
174
      -- and soft wrap opportunities: ignored here.
175
      -- There's also some explanations about CSS, italic correction etc. which we ignore too.
176
      text = text:gsub("[\n\r]", " ")
×
177
      return b.text("string", {}, scriptType.upright, text:gsub("%s+", " "))
×
178
   elseif content.command == "maction" then
×
179
      -- MathML Core 3.6: display as mrow, ignoring all but the first child
180
      return b.stackbox("H", { convertFirstChild(content) })
×
181
   elseif content.command == "mstyle" then
×
182
      -- It's an mrow, but with some style attributes that we ignore.
183
      SU.warn("MathML mstyle is not fully supported yet")
×
184
      return b.stackbox("H", convertChildren(content))
×
185
   elseif content.command == "mpadded" then
×
186
      -- MathML Core 3.3.6.1: The <mpadded> element generates an anonymous <mrow> box
187
      -- called the "impadded inner box"
188
      return b.padded(content.options, b.stackbox("H", convertChildren(content)))
×
189
   else
190
      SU.error("Unknown math command " .. content.command)
×
191
   end
192
end
193

194
local function handleMath (_, mbox, options)
195
   local mode = options and options.mode or "text"
×
196
   local counter = SU.boolean(options.numbered, false) and "equation"
×
197
   counter = options.counter or counter -- overrides the default "equation" counter
×
198

199
   if mode == "display" then
×
200
      mbox.mode = b.mathMode.display
×
201
   elseif mode == "text" then
×
202
      mbox.mode = b.mathMode.textCramped
×
203
   else
204
      SU.error("Unknown math mode " .. mode)
×
205
   end
206

207
   SU.debug("math", function ()
×
208
      return "Resulting mbox: " .. tostring(mbox)
×
209
   end)
210
   mbox:styleDescendants()
×
211
   mbox:shapeTree()
×
212

213
   if mode == "display" then
×
214
      SILE.typesetter:endline()
×
215
      SILE.typesetter:pushExplicitVglue(SILE.settings:get("math.displayskip"))
×
216
      SILE.settings:temporarily(function ()
×
217
         -- Center the equation in the space available up to the counter (if any),
218
         -- respecting the fixed part of the left and right skips.
219
         local lskip = SILE.settings:get("document.lskip") or SILE.types.node.glue()
×
220
         local rskip = SILE.settings:get("document.rskip") or SILE.types.node.glue()
×
221
         SILE.settings:set("document.parindent", SILE.types.node.glue())
×
222
         SILE.settings:set("current.parindent", SILE.types.node.glue())
×
223
         SILE.settings:set("document.lskip", SILE.types.node.hfillglue(lskip.width.length))
×
224
         SILE.settings:set("document.rskip", SILE.types.node.glue(rskip.width.length))
×
225
         SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue())
×
226
         SILE.settings:set("document.spaceskip", SILE.types.length("1spc", 0, 0))
×
227
         SILE.typesetter:pushHorizontal(mbox)
×
228
         SILE.typesetter:pushExplicitGlue(SILE.types.node.hfillglue())
×
229
         if counter then
×
230
            options.counter = counter
×
231
            SILE.call("increment-counter", { id = counter })
×
232
            SILE.call("math:numberingstyle", options)
×
233
         elseif options.number then
×
234
            SILE.call("math:numberingstyle", options)
×
235
         end
236
         SILE.typesetter:endline()
×
237
      end)
238
      SILE.typesetter:pushExplicitVglue(SILE.settings:get("math.displayskip"))
×
239
   else
240
      SILE.typesetter:pushHorizontal(mbox)
×
241
   end
242
end
243

244
return { ConvertMathML, handleMath }
×
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