• 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

85.11
/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")
10✔
3
local syms = require("packages.math.unicode-symbols")
10✔
4

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

22
local ConvertMathML
23

24
local function convertChildren (tree)
25
   local mboxes = {}
541✔
26
   for _, n in ipairs(tree) do
2,542✔
27
      local box = ConvertMathML(nil, n)
2,001✔
28
      if box then
2,001✔
29
         table.insert(mboxes, box)
1,461✔
30
      end
31
   end
32
   return mboxes
541✔
33
end
34

35
-- convert MathML into mbox
36
function ConvertMathML (_, content)
10✔
37
   if content == nil or content.command == nil then
2,063✔
38
      return nil
540✔
39
   end
40
   if content.command == "math" or content.command == "mathml" then -- toplevel
1,523✔
41
      return b.stackbox("V", convertChildren(content))
124✔
42
   elseif content.command == "mrow" then
1,461✔
43
      return b.stackbox("H", convertChildren(content))
526✔
44
   elseif content.command == "mi" then
1,198✔
45
      local script = content.options.mathvariant and b.mathVariantToScriptType(content.options.mathvariant)
349✔
46
      local text = content[1]
349✔
47
      if type(text) ~= "string" then
349✔
48
         SU.error("mi command contains " .. text .. ", which is not text")
×
49
      end
50
      script = script or (luautf8.len(text) == 1 and b.scriptType.italic or b.scriptType.upright)
349✔
51
      return b.text("identifier", {}, script, text)
349✔
52
   elseif content.command == "mo" then
849✔
53
      local script = content.options.mathvariant and b.mathVariantToScriptType(content.options.mathvariant)
368✔
54
         or b.scriptType.upright
368✔
55
      local text = content[1]
368✔
56
      local attributes = {}
368✔
57
      if syms.symbolDefaults[text] then
368✔
58
         for attribute, value in pairs(syms.symbolDefaults[text]) do
777✔
59
            attributes[attribute] = value
440✔
60
         end
61
      end
62
      if content.options.atom then
368✔
63
         if not atomTypeShort[content.options.atom] then
6✔
64
            SU.error("Unknown atom type " .. content.options.atom)
×
65
         else
66
            attributes.atom = atomTypeShort[content.options.atom]
6✔
67
         end
68
      end
69
      if type(text) ~= "string" then
368✔
70
         SU.error("mo command contains " .. text .. ", which is not text")
×
71
      end
72
      return b.text("operator", attributes, script, text)
368✔
73
   elseif content.command == "mn" then
481✔
74
      local script = content.options.mathvariant and b.mathVariantToScriptType(content.options.mathvariant)
207✔
75
         or b.scriptType.upright
207✔
76
      local text = content[1]
207✔
77
      if type(text) ~= "string" then
207✔
78
         SU.error("mn command contains " .. text .. ", which is not text")
×
79
      end
80
      if string.sub(text, 1, 1) == "-" then
414✔
81
         text = "−" .. string.sub(text, 2)
2✔
82
      end
83
      return b.text("number", {}, script, text)
207✔
84
   elseif content.command == "mspace" then
274✔
85
      return b.space(content.options.width, content.options.height, content.options.depth)
58✔
86
   elseif content.command == "msub" then
216✔
87
      local children = convertChildren(content)
60✔
88
      if #children ~= 2 then
60✔
89
         SU.error("Wrong number of children in msub")
×
90
      end
91
      return b.newSubscript({ base = children[1], sub = children[2] })
60✔
92
   elseif content.command == "msup" then
156✔
93
      local children = convertChildren(content)
28✔
94
      if #children ~= 2 then
28✔
95
         SU.error("Wrong number of children in msup")
×
96
      end
97
      return b.newSubscript({ base = children[1], sup = children[2] })
28✔
98
   elseif content.command == "msubsup" then
128✔
99
      local children = convertChildren(content)
14✔
100
      if #children ~= 3 then
14✔
101
         SU.error("Wrong number of children in msubsup")
×
102
      end
103
      return b.newSubscript({ base = children[1], sub = children[2], sup = children[3] })
14✔
104
   elseif content.command == "munder" then
114✔
105
      local children = convertChildren(content)
1✔
106
      if #children ~= 2 then
1✔
107
         SU.error("Wrong number of children in munder")
×
108
      end
109
      return b.newUnderOver({ base = children[1], sub = children[2] })
1✔
110
   elseif content.command == "mover" then
113✔
111
      local children = convertChildren(content)
×
112
      if #children ~= 2 then
×
113
         SU.error("Wrong number of children in mover")
×
114
      end
115
      return b.newUnderOver({ base = children[1], sup = children[2] })
×
116
   elseif content.command == "munderover" then
113✔
117
      local children = convertChildren(content)
24✔
118
      if #children ~= 3 then
24✔
119
         SU.error("Wrong number of children in munderover")
×
120
      end
121
      return b.newUnderOver({ base = children[1], sub = children[2], sup = children[3] })
24✔
122
   elseif content.command == "mfrac" then
89✔
123
      local children = convertChildren(content)
33✔
124
      if #children ~= 2 then
33✔
125
         SU.error("Wrong number of children in mfrac: " .. #children)
×
126
      end
127
      return b.fraction(children[1], children[2])
33✔
128
   elseif content.command == "mtable" or content.command == "table" then
56✔
129
      local children = convertChildren(content)
8✔
130
      return b.table(children, content.options)
8✔
131
   elseif content.command == "mtr" then
48✔
132
      return b.mtr(convertChildren(content))
24✔
133
   elseif content.command == "mtd" then
36✔
134
      return b.stackbox("H", convertChildren(content))
72✔
135
   else
136
      SU.error("Unknown math command " .. content.command)
×
137
   end
138
end
139

140
local function handleMath (_, mbox, options)
141
   local mode = options and options.mode or "text"
62✔
142
   local counter = SU.boolean(options.numbered, false) and "equation"
124✔
143
   counter = options.counter or counter -- overrides the default "equation" counter
62✔
144

145
   if mode == "display" then
62✔
146
      mbox.mode = b.mathMode.display
34✔
147
   elseif mode == "text" then
28✔
148
      mbox.mode = b.mathMode.textCramped
28✔
149
   else
150
      SU.error("Unknown math mode " .. mode)
×
151
   end
152

153
   SU.debug("math", function ()
124✔
154
      return "Resulting mbox: " .. tostring(mbox)
×
155
   end)
156
   mbox:styleDescendants()
62✔
157
   mbox:shapeTree()
62✔
158

159
   if mode == "display" then
62✔
160
      SILE.typesetter:endline()
34✔
161
      SILE.typesetter:pushExplicitVglue(SILE.settings:get("math.displayskip"))
68✔
162
      SILE.settings:temporarily(function ()
68✔
163
         -- Center the equation in the space available up to the counter (if any),
164
         -- respecting the fixed part of the left and right skips.
165
         local lskip = SILE.settings:get("document.lskip") or SILE.types.node.glue()
68✔
166
         local rskip = SILE.settings:get("document.rskip") or SILE.types.node.glue()
68✔
167
         SILE.settings:set("document.parindent", SILE.types.node.glue())
68✔
168
         SILE.settings:set("current.parindent", SILE.types.node.glue())
68✔
169
         SILE.settings:set("document.lskip", SILE.types.node.hfillglue(lskip.width.length))
68✔
170
         SILE.settings:set("document.rskip", SILE.types.node.glue(rskip.width.length))
68✔
171
         SILE.settings:set("typesetter.parfillskip", SILE.types.node.glue())
68✔
172
         SILE.settings:set("document.spaceskip", SILE.types.length("1spc", 0, 0))
68✔
173
         SILE.typesetter:pushHorizontal(mbox)
34✔
174
         SILE.typesetter:pushExplicitGlue(SILE.types.node.hfillglue())
68✔
175
         if counter then
34✔
176
            options.counter = counter
×
177
            SILE.call("increment-counter", { id = counter })
×
178
            SILE.call("math:numberingstyle", options)
×
179
         elseif options.number then
34✔
180
            SILE.call("math:numberingstyle", options)
×
181
         end
182
         SILE.typesetter:endline()
34✔
183
      end)
184
      SILE.typesetter:pushExplicitVglue(SILE.settings:get("math.displayskip"))
102✔
185
   else
186
      SILE.typesetter:pushHorizontal(mbox)
28✔
187
   end
188
end
189

190
return { ConvertMathML, handleMath }
10✔
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