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

sile-typesetter / sile / 11622284370

01 Nov 2024 12:54AM UTC coverage: 63.912% (+3.1%) from 60.798%
11622284370

push

github

web-flow
Merge 4f33d9751 into 5dffc31aa

113 of 174 new or added lines in 5 files covered. (64.94%)

166 existing lines in 6 files now uncovered.

11632 of 18200 relevant lines covered (63.91%)

5084.73 hits per line

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

77.08
/packages/math/init.lua
1
local base = require("packages.base")
10✔
2

3
local package = pl.class(base)
10✔
4
package._name = "math"
10✔
5

6
function package:_init ()
10✔
7
   base._init(self)
10✔
8
   local typesetter = require("packages.math.typesetter")
10✔
9
   self.ConvertMathML, self.handleMath = typesetter[1], typesetter[2]
10✔
10
   local texlike = require("packages.math.texlike")
10✔
11
   self.convertTexlike, self.compileToMathML = texlike[1], texlike[2]
10✔
12
   -- Register a new unit that is 1/18th of the current math font size
13
   SILE.registerUnit("mu", {
20✔
14
      relative = true,
15
      definition = function (value)
16
         return value * SILE.settings:get("math.font.size") / 18
1,150✔
17
      end,
18
   })
19
   self:loadPackage("counters")
10✔
20
end
21

22
function package.declareSettings (_)
10✔
23
   SILE.settings:declare({
10✔
24
      parameter = "math.font.family",
25
      type = "string",
26
      default = "Libertinus Math",
27
   })
28
   SILE.settings:declare({
10✔
29
      parameter = "math.font.style",
30
      type = "string",
31
      default = "Regular",
32
   })
33
   SILE.settings:declare({
10✔
34
      parameter = "math.font.weight",
35
      type = "integer",
36
      default = 400,
37
   })
38
   SILE.settings:declare({
10✔
39
      parameter = "math.font.filename",
40
      type = "string",
41
      default = "",
42
   })
43
   SILE.settings:declare({
20✔
44
      parameter = "math.font.size",
45
      type = "number or integer",
46
      default = SILE.settings:get("font.size"),
20✔
47
   })
48
   SILE.settings:registerHook ("font.size", function (size)
20✔
49
      -- Follow document font size changes
NEW
50
      SILE.settings:set("math.font.size", size)
×
51
   end)
52
   -- Whether to show debug boxes around mboxes
53
   SILE.settings:declare({
10✔
54
      parameter = "math.debug.boxes",
55
      type = "boolean",
56
      default = false,
57
   })
58
   SILE.settings:declare({
20✔
59
      parameter = "math.displayskip",
60
      type = "VGlue",
61
      default = SILE.types.node.vglue("2ex plus 1pt"),
20✔
62
   })
63
end
64

65
function package:registerCommands ()
10✔
66
   self:registerCommand("mathml", function (options, content)
20✔
67
      local mbox
68
      xpcall(function ()
44✔
69
         mbox = self:ConvertMathML(content)
44✔
70
      end, function (err)
44✔
UNCOV
71
         print(err)
×
UNCOV
72
         print(debug.traceback())
×
73
      end)
74
      self:handleMath(mbox, options)
22✔
75
   end)
76

77
   self:registerCommand("math", function (options, content)
20✔
78
      local mbox
79
      xpcall(function ()
80✔
80
         mbox = self:ConvertMathML(self:compileToMathML({}, self:convertTexlike(content)))
160✔
81
      end, function (err)
80✔
UNCOV
82
         print(err)
×
UNCOV
83
         print(debug.traceback())
×
84
      end)
85
      self:handleMath(mbox, options)
40✔
86
   end)
87

88
   self:registerCommand("math:numberingstyle", function (options, _)
20✔
UNCOV
89
      SILE.typesetter:typeset("(")
×
UNCOV
90
      if options.counter then
×
UNCOV
91
         SILE.call("show-counter", { id = options.counter })
×
UNCOV
92
      elseif options.number then
×
93
         SILE.typesetter:typeset(options.number)
×
94
      end
95
      SILE.typesetter:typeset(")")
×
96
   end)
97
end
98

99
package.documentation = [[
100
\begin{document}
101
\use[module=packages.math]
102
\set[parameter=math.font.family, value=Libertinus Math]
103
\set[parameter=math.font.size, value=11]
104
% Default verbatim font (Hack) is missing a few math symbols
105
\use[module=packages.font-fallback]
106
\font:add-fallback[family=Symbola]
107
\define[command=paragraph]{\smallskip\em{\process.}\novbreak\par}
108
The \autodoc:package{math} package provides typesetting of formulas directly in a SILE document.
109

110
\autodoc:note{Mathematical typesetting in SILE is still in its infancy.
111
As such, it lacks some features and may contain bugs.
112
Feedback and contributions are always welcome.}
113

114
\noindent To typeset mathematics, you will need an OpenType math font installed on your system.%
115
%\footnote{A list of freely available math fonts can be found at \href[src=https://www.ctan.org/pkg/unicode-math]{https://www.ctan.org/pkg/unicode-math}}
116
By default, this package uses Libertinus Math, so it will fail if Libertinus Math can’t be found.
117
Another font may be specified via the setting \autodoc:setting{math.font.family}.
118
If required, you can set the font style and weight via \autodoc:setting{math.font.style} and \autodoc:setting{math.font.weight}.
119
The font size can be set via \autodoc:setting{math.font.size}.
120

121
\paragraph{MathML}
122
The first way to typeset math formulas is to enter them in the MathML format.
123
MathML is a standard for encoding mathematical notation for the Web and for other types of digital documents.
124
It is supported by a wide range of tools and represents the most promising format for unifying the encoding of mathematical notation, as well as improving its accessibility (e.g., to blind users).
125

126
To render an equation encoded in MathML, simply put it in a \code{mathml} command.
127
For example, the formula \mathml{\mrow{\msup{\mi{a}\mn{2}} \mo{+} \msup{\mi{b}\mn{2}} \mo{=} \msup{\mi{c}\mn{2}}}} was typeset by the following command:
128

129
\begin[type=autodoc:codeblock]{raw}
130
\mathml{
131
    \mrow{
132
        \msup{\mi{a}\mn{2}}
133
        \mo{+}
134
        \msup{\mi{b}\mn{2}}
135
        \mo{=}
136
        \msup{\mi{c}\mn{2}}
137
    }
138
}
139
\end{raw}
140

141
\noindent In an XML document, we could use the more classical XML syntax:
142

143
\begin[type=autodoc:codeblock]{raw}
144
<mathml>
145
    <mrow>
146
        <msup> <mi>a</mi> <mn>2</mn> </msup>
147
        <mo>+</mo>
148
        <msup> <mi>b</mi> <mn>2</mn> </msup>
149
        <mo>=</mo>
150
        <msup> <mi>c</mi> <mn>2</mn> </msup>
151
    </mrow>
152
</mathml>
153
\end{raw}
154

155
\noindent By default, formulas are integrated into the flow of text.
156
To typeset them on their own line, use the \autodoc:parameter{mode=display} option:
157

158
\mathml[mode=display]{
159
    \mrow{
160
        \msup{\mi{a}\mn{2}}
161
        \mo{+}
162
        \msup{\mi{b}\mn{2}}
163
        \mo{=}
164
        \msup{\mi{c}\mn{2}}
165
    }
166
}
167

168
\paragraph{TeX-like syntax}
169
As the previous examples illustrate, MathML is not really intended to be written by humans and quickly becomes very verbose.
170
That is why this package also provides a \code{math} command, which understands a syntax similar to the math syntax of TeX.
171
To typeset the above equation, one only has to type \code{\\math\{a^2 + b^2 = c^2\}}.
172

173
Here is a slightly more involved equation:
174

175
\begin[type=autodoc:codeblock]{raw}
176
\begin[mode=display]{math}
177
    \sum_{n=1}^\infty \frac{1}{n^2} = \frac{\pi^2}{6}
178
\end{math}
179
\end{raw}
180

181
\noindent This renders as:
182

183
\begin[mode=display]{math}
184
    \sum_{n=1}^\infty \frac{1}{n^2} = \frac{\pi^2}{6}
185
\end{math}
186

187
The general philosophy of the TeX-like syntax is to be a simple layer on top of MathML, and not to mimic perfectly the syntax of the LaTeX tool.
188
Its main difference from the SILE syntax is that \code{\\mycommand\{arg1\}\{arg2\}\{arg3\}} is translated into MathML as \code{<mycommand> arg1 arg2 arg3 </mycommand>} whereas in normal SILE syntax, the XML equivalent would be \code{<mycommand>arg1</mycommand> arg2 arg3}.
189

190
\code{\\sum}, \code{\\infty}, and \code{\\pi} are only shorthands for the Unicode characters \math{\sum}, \math{\infty} and \math{\pi}.
191
If it’s more convenient, you can use these Unicode characters directly.
192
The symbol shorthands are the same as in the TeX package \href[src=https://www.ctan.org/pkg/unicode-math]{\code{unicode-math}}.
193

194
\code{\{formula\}} is a shorthand for \code{\\mrow\{formula\}}.
195
Since parentheses—among other glyphs—stretch vertically to the size of their englobing \code{mrow}, this is useful to typeset parentheses of different sizes on the same line:
196

197
\begin[type=autodoc:codeblock]{raw}
198
\Gamma (\frac{\zeta}{2}) + x^2(x+1)
199
\end{raw}
200

201
\noindent renders as
202

203
\begin[mode=display]{math}
204
    \Gamma (\frac{\zeta}{2}) + x^2(x+1)
205
\end{math}
206

207
\noindent which is ugly.
208
To keep parentheses around \math{x+1} small, you should put braces around the expression:
209

210
\begin[type=autodoc:codeblock]{raw}
211
\Gamma (\frac{\zeta}{2}) + x^2{(x+1)}
212
\end{raw}
213

214
\begin[mode=display]{math}
215
    \Gamma (\frac{\zeta}{2}) + x^2{(x+1)}
216
\end{math}
217

218
\noindent To print a brace in a formula, you need to escape it with a backslash.
219

220
\paragraph{Token kinds}
221
In the \code{math} syntax, every individual letter is an identifier (MathML tag \code{mi}), every number is a… number (tag \code{mn}) and all other characters are operators (tag \code{mo}).
222
If this does not suit you, you can explicitly use the \code{\\mi}, \code{\\mn}, or \code{\\mo} tags.
223
For instance, \code{sin(x)} will be rendered as \math{sin(x)}, because SILE considers the letters s, i and n to be individual identifiers, and identifiers made of one character are italicized by default.
224
To avoid that, you can specify that \math{\mi{sin}} is an identifier by writing \code{\\mi\{sin\}(x)} and get: \math{\mi{sin}(x)}.
225
If you prefer it in “double struck” style, this is permitted by the \code{mathvariant} attribute: \code{\\mi[mathvariant=double-struck]\{sin\}(x)} renders as \math{\mi[mathvariant=double-struck]{sin}(x)}.
226

227
\paragraph{Atom types and spacing}
228
Each token automatically gets assigned an atom type from the list below:
229
\begin{itemize}
230
  \item{\code{ord}: \code{mi} and \code{mn} tokens, as well as unclassified operators}
231
  \item{\code{big}: big operators like ‘\math{\sum}’ or ‘\math{\prod}’}
232
  \item{\code{bin}: binary operators like ‘\math{+}’ or ‘\math{\%}’}
233
  \item{\code{rel}: relation operators like ‘\math{=}’ or ‘\math{<}’}
234
  \item{\code{open}: opening operators like ‘\math{(}’ or ‘\math{[}’}
235
  \item{\code{close}: closing operators like ‘\math{)}’ or ‘\math{]}’}
236
  \item{\code{punct}: punctuation operators like ‘\math{,}’}
237
  % TODO: Those are defined in the 'math' package but appear to be unused
238
  %\item{\code{inner}}
239
  %\item{\code{over}}
240
  %\item{\code{under}}
241
  %\item{\code{accent}}
242
  %\item{\code{radical}}
243
  %\item{\code{vcenter}}
244
\end{itemize}
245
\noindent The spacing between any two successive tokens is set automatically based on their atom types, and hence may not reflect the actual spacing used in the input.
246
To make an operator behave like it has a certain atom type, you can use the \code{atom} attribute. For example, \code{a \\mo[atom=bin]\{div\} b} renders as \math[mode=display]{a \mo[atom=bin]{div} b.}
247

248
Spaces in math mode are defined in “math units” (mu), which are 1/18 of an em of the current \em{math} font (and are independent of the current text font size).
249
Standard spaces inserted automatically between tokens come in three varieties: thin (3 mu), medium (4 mu) and thick (5 mu).
250
If needed, you can insert them manually with the \code{\\thinspace} (or \code{\\,}), \code{\\medspace} (or \code{\\>}), and \code{\\thickspace} (or \code{\\;}) commands.
251
Negative space counterparts are available as \code{\\negthinspace} (or \code{\\!}), \code{\\negmedspace}, and \code{\\negthickspace}.
252
The \code{\\enspace}, \code{\\quad}, and \code{\\qquad} commands from normal text mode are also available, but the spaces they insert scale relative to the text font size.
253
Finally, you can add a space of any size using the \code{\\mspace[width=<dimension>]} command.
254

255
\paragraph{Macros}
256
To save you some typing, the math syntax lets you define macros with the following syntax:
257

258
\begin[type=autodoc:codeblock]{raw}
259
\def{macro-name}{macro-body}
260
\end{raw}
261

262
\noindent where in the macro’s body \code{#1}, \code{#2}, etc. will be replaced by the macro’s arguments.
263
For instance:
264

265
\begin[type=autodoc:codeblock]{raw}
266
\begin[mode=display]{math}
267
    \def{diff}{\mfrac{\mo{d}#1}{\mo{d}#2}}
268
    \def{bi}{\mi[mathvariant=bold-italic]{#1}}
269

270
    \diff{\bi{p}}{t} = ∑_i \bi{F}_i
271
\end{math}
272
\end{raw}
273

274
\noindent results in:
275

276
\begin[mode=display]{math}
277
  \def{diff}{\mfrac{\mo{d}#1}{\mo{d}#2}}
278
  \def{bi}{\mi[mathvariant=bold-italic]{#1}}
279
  \diff{\bi{p}}{t} = ∑_i \bi{F}_i
280
\end{math}
281

282
When macros are not enough, creating new mathematical elements is quite simple: one only needs to create a new class deriving from \code{mbox} (defined in \code{packages/math/base-elements.lua}) and define the \code{shape} and \code{output} methods.
283
\code{shape} must define the \code{width}, \code{height} and \code{depth} attributes of the element, while \code{output} must draw the actual output.
284
An \code{mbox} may have one or more children (for instance, a fraction has two children—its numerator and denominator).
285
The \code{shape} and \code{output} methods of the children are called automatically.
286

287
\paragraph{Matrices, aligned equations, and other tables}
288
Tabular math can be typeset using the \code{table} command (or equivalently the \code{mtable} MathML tag).
289
For instance, to typeset a matrix:
290

291
\begin[type=autodoc:codeblock]{raw}
292
\begin[mode=display]{math}
293
    (
294
    \table{
295
        1 & 2 & 7 \\
296
        0 & 5 & 3 \\
297
        8 & 2 & 1 \\
298
    }
299
    )
300
\end{math}
301
\end{raw}
302

303
\noindent will yield:
304

305
\begin[mode=display]{math}
306
  (\table{
307
       1 & 2 & 7 \\
308
       0 & 5 & 3 \\
309
       8 & 2 & 1 \\
310
  })
311
\end{math}
312

313
\noindent Tables may also be used to control the alignment of formulas:
314

315
\begin[type=autodoc:codeblock]{raw}
316
\begin[mode=display]{math}
317
    \{
318
    \table[columnalign=right center left]{
319
        u_0 &=& 1 \\
320
        u_1 &=& 1 \\
321
        u_n &=& u_{n−1} + u_{n−2}, \forall n ⩾ 2 \\
322
    }
323
\end{math}
324
\end{raw}
325

326
\begin[mode=display]{math}
327
    \{
328
    \table[columnalign=right center left]{
329
        u_0 &=& 1 \\
330
        u_1 &=& 1 \\
331
        u_n &=& u_{n−1} + u_{n−2}, \forall n ⩾ 2 \\
332
    }
333
\end{math}
334

335
\noindent Tables currently do not support all attributes required by the MathML standard, but they do allow to control spacing using the \code{rowspacing} and \code{columnspacing} options.
336

337
Finally, here is a little secret. This notation:
338

339
\begin[type=autodoc:codeblock]{raw}
340
\table{
341
    1 & 2 & 7 \\
342
    0 & 5 & 3 \\
343
    8 & 2 & 1 \\
344
}
345
\end{raw}
346

347
\noindent is strictly equivalent to this one:
348

349
\begin[type=autodoc:codeblock]{raw}
350
\table{
351
        {1} {2} {7}
352
    }{
353
        {0} {5} {3}
354
    }{
355
        {8} {2} {1}
356
    }
357
}
358
\end{raw}
359

360
\noindent In other words, the notation using \code{&} and \code{\\\\} is only a syntactic sugar for a two-dimensional array constructed with braces.
361

362
\paragraph{Numbered equations}
363
Equations can be numbered in display mode.
364

365
When \autodoc:parameter{numbered=true}, equations are numbered using a default “equation” counter:
366
\math[mode=display, numbered=true]{e^{i\pi} = -1}
367

368
A different counter can be set by using the option \autodoc:parameter{counter=<id>}, and this setting will also enable numbering.
369

370
It is also possible to impose direct numbering using the \autodoc:parameter{number=<value>} option.
371

372
The default numbering format is \autodoc:example{(n)}, but this style may be overridden by defining a custom \autodoc:command{\math:numberingstyle} command.
373
The \code{counter} or the direct value \code{number} is passed as a parameter to this hook, as well as any other options.
374

375
\paragraph{Missing features}
376
This package still lacks support for some mathematical constructs, but hopefully we’ll get there.
377
Among unsupported constructs are: decorating symbols with so-called accents, such as arrows or hats, “over” or “under” braces, and line breaking inside a formula.
378

379
\font:remove-fallback
380
\end{document}
381
]]
10✔
382

383
return package
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