CTAN Comprehensive TeX Archive Network

Verzeichnis macros/luatex/latex/scholatex

README.md

scholatex

Print-ready teaching worksheets, without writing . — A small, consistent tag language for the documents a teacher actually makes.

CTAN Version Engine TeX Live License

Why scholatex?

Write a single .tex file with a tiny, readable syntax and get a clean, print-ready worksheet — framed exercises, a results table, simple formulas, an image — without \begin{tabular}{|c|c|}, without counting ampersands, without remembering which package draws a coloured box.

% !TeX program = lualatex
\documentclass[margins=20, size=12]{scholatex}
\begin{document}

<Navy b 18pt c>My first scholatex document

This is a normal paragraph. <b>{Bold}, <i>{italic}, <Red>{red}.

<box line:Navy fill:AliceBlue radius:3 title:{A framed note}>{
Boxes, tables, images and maths all use the same tag syntax.
}

\end{document}

Compile with lualatex myfile.tex — the scholatex class reads the body between \begin{document} and \end{document}, transpiles it to , and typesets it. The output has full quality; the syntax is meant to be read and edited in minutes by someone who does not know . scholatex is a closed language: the backslash is an ordinary character, so raw commands in the body are typeset literally rather than executed. Everything a worksheet needs is expressed through tags, which keeps documents consistent and safe to share.

Quick start

tlmgr install scholatex      # add sudo on macOS/Linux; see Installation below
\documentclass[margins=20, size=12, lang=en]{scholatex}
\begin{document}
<Navy b section>First topic
A paragraph with <b>{bold} and <Red>{colour}.
\end{document}

Key features

  • 🏷️ One tag syntax<attributes>{content} covers text, tables, images, maths, boxes, lists and full-page layouts
  • 🎨 151 colours — the full CSS / svgnames palette in CamelCase, 22 of them with a lowercase shortcut
  • 📐 A maths mini-language — fractions, roots, sums, products, integrals, derivatives, trigonometry, matrices and systems, all in $...$
  • 📦 Framed boxes & grids — coloured <box> panels and CSS-Grid-style named-area page layouts
  • 📊 Tables without pain — two-letter cell placement, spans, headers, borders, no ampersand counting
  • ♻️ Aliases & macros — factor a style once, name it everywhere; one edit restyles the whole document
  • 🔁 Control flow — loops, conditionals and #{...} interpolation in the document body
  • 🔒 Sandbox optionuntrusted=true runs document Lua in a restricted environment

The one rule

Everything is a tag: <attributes> followed either by {content} (inline) or by a line that ends in { (a block). Attribute words follow a single case convention:

Form Meaning Examples
lowercase a short keyword (style, alignment, skip) b, i, c, 2tab
CamelCase an extended CSS colour (151 of them) SteelBlue, Crimson
UPPERCASE a font name DEJAVU SANS

The order of words inside a tag never matters — emission is always normalised (page break, then vertical skips, then alignment, then tabs, then styles).


Installation

scholatex is on CTAN and ships with Live, so on a current, fully updated Live or Mac it is already there — compile with lualatex and nothing more is needed. If your installation predates the package, install it once with the Live manager; the same two commands work on macOS, Linux and Windows:

tlmgr update --self
tlmgr install scholatex

On macOS (Mac) and most Linux setups tlmgr needs administrator rights, so prefix both with sudo. On Windows, open the Live Command-Line (or a terminal as Administrator) and run them without sudo. MiK users install through the MiK Console (Packages → search scholatexInstall), or with mpm --install=scholatex.

tlmgr update --self comes first because the manager refuses to install packages when its own version is older than the repository's. After installing, check the class is found:

kpsewhich scholatex.cls

It should print a path under your tree. From then on \documentclass{scholatex} works from any folder.

If tlmgr install scholatex reports the package is not present in the repository, your mirror has not yet synced a recent release; either wait a day or switch to the main CTAN mirror and retry:

sudo tlmgr option repository https://mirror.ctan.org/systems/texlive/tlnet
sudo tlmgr update --self
sudo tlmgr install scholatex

Manual install (any OS, no waiting)

To use the package immediately without tlmgr, drop the files into your personal tree, mirroring the CTAN layout, then refresh the filename database. The home tree is ~/Library/texmf on macOS, ~/texmf on Linux, and %USERPROFILE%\texmf on Windows:

mkdir -p ~/texmf/tex/luatex/latex/scholatex
cp scholatex.cls scholatex.lua scholatex-*.lua ~/texmf/tex/luatex/latex/scholatex/
mktexlsr ~/texmf

A Lua engine is required (lualatex); the package does not compile with pdflatex or xelatex.


## Class options

Set in \documentclass[...]{scholatex}:

Option Default Meaning
margins 20 N (all sides) or {top,right,bottom,left} in mm
font Latin Modern Roman main text font
mathfont Latin Modern Math math font
size 11 base font size in pt
imgdir img folder(s) searched for bare image names; comma-separated list, e.g. {IMG, IMAGES/PNG}
tabwidth 8 width of one tab, in mm (a large Seyès square)
lineheight 8 height of one explicit line skip (<line>, <Nlines>), in mm
linespread 1.0 overall line spacing (1.5 = one-and-a-half); tall maths never touches even at 1.0
scriptscale 100 scale (%) of up/down scripts
padding 2 inner padding (mm) between a box/grid frame and its content; override locally with sep:N
lang fr decimal separator: fr (comma) or en (point); affects typed and interpolated decimals alike
precision -1 decimals a computed #{...} value is rounded to for display (-1 = no rounding); round(x, d) overrides locally
untrusted false run document Lua in a restricted sandbox — see Security

Headings carry no extra vertical space or built-in colour: to style one, fold a heading keyword into an alias, e.g. let h = <line Navy b section> then <h>My title.


Text attributes

Inline stylesb bold, i italic, u underline, emph, sf sans-serif, sc small caps. They combine in one tag: <b i red>{bold italic red}.

Colours — a colour is always one of the 151 CSS colours, written in CamelCase: Navy, Red, Tomato, SteelBlue, ForestGreen, …. One rule, no lowercase shortcuts — the everyday colours are simply capitalised (Red, Blue, Green, Gray). See the colour reference.

Fonts and sizes — a font name in CAPITALS (<DEJAVU SANS>{…}); sizes as Npt or Npx (<14pt>{…}).

Alignmentl left, c centre, r right, j justified.

Tabs and skips (the number is always a prefix) — Ntab indents the first line by N tabs; vertical skips obey singular/plural agreement: line or 1line skips one, 2lines, 3lines, … skip several. Bare tab = 1tab.

ScriptsupN raises text by N mm, downN lowers it: x<up4>{2}, H<down2>{2}O.

Page breaknextpage.

Section headingssection, subsection, subsubsection give the three levels, numbered automatically:

<section>First topic
<subsection>A detail
<subsubsection>A finer point

renders as 1 First topic, 1.1 A detail, 1.1.1 A finer point. A table of contents is printed with <tableofcontents>; give it a title in braces: <tableofcontents>{Table of contents}.

Numbering style — by default the numbers are hierarchical (1, then 1.1, then 1.1.1). A counter keyword on a heading changes the style of that level, on its own — no inherited prefix: num (1, 2, 3), roman (i, ii, iii), ROMAN (I, II, III), alpha (a, b, c), ALPHA (A, B, C). For example let study = <Navy b section ROMAN> and let step = <Navy b subsection num> give sections I, II and, under each, steps 1, 2, 3 (not I.1). Each level is independent; without a keyword, the default hierarchical numbering stands.


Aliases and macros — the factoring tool

Define a style once, at the top of the document, then name it everywhere instead of repeating its attributes. One edit at the definition restyles the whole document.

let title = <Navy b 18pt c>          % style alias
let h1    = <Navy b section>         % a heading style, reusable
let p     = <tab>                    % a standard indented paragraph
<title>My heading
<h1>First topic
<p>{ A paragraph, indented and justified, named not described. }

let n = 7                            % value, usable in #{...}
Seven squared is #{n*n}.

let greet{name} = Hello #name!       % text macro with parameters

Change let h1 = <Navy b section> to <ForestGreen b section> once and every first-level heading follows — the single point of control that keeps a long worksheet consistent.


Tables

Columns are declared in brackets, one two-letter placement code per column. The first letter is vertical (t/m/b), the second horizontal (l/c/r): mc is middle-centre, br bottom-right. This is the only placement syntax scholatex uses — in tables as in boxes and grids.

<table [mc, ml, mc, mc] borders header fill:AliceBlue line:Navy headerfill:Navy headertext:White>{
<colspan:4 mc>{Term report}
Day | Subject | Mark | Coef.
<rowspan:2 mc>{Monday} | Maths | 15 | 4
. | French | 12 | 3
}

One row per line, | between cells. <colspan:N> and <rowspan:N> span cells; . marks a cell covered by a span above. N: before a placement code fixes a column width in mm.


Images

<img 30>{photo.png}        % 30 mm wide
<img 40x25>{photo.png}     % 40 mm × 25 mm
<img>{photo.png}           % full available width, never enlarged

A bare name is searched in each folder of imgdir in turn, then at the project root. An explicit path always works (<img 20>{IMG/PNG/chat.png}).


## Maths

Wrap maths in $…$. A small mini-language keeps it light:

You write You get
* ×
+- ±
<= >= != ≤ ≥ ≠
a/b fraction (chained a/b/c reads as (a/b)/c)
x^2 x_i power / index (bind tighter than /, so x^2/y is \frac{x^2}{y})
sqrt(2) √2
sum(i=1, n) i ∑ with bounds, display style
prod(k=1, n) k ∏ with bounds, display style
int(x) f(x) ∫ f(x) dx (primitive; the differential is added)
int(x=a, b) f(x) ∫ from a to b, f(x) dx
contourint(C) f(z) ∮ contour integral
pvint(x=a, b) f(x) p.v. ∫ Cauchy principal value
meanint(x=a, b) f(x) ⨍ average (normalised) integral
dy/dx, df/dx derivative, upright differential d (ISO)
sin(x) cos(x) ln(x) upright function names
abs(x) x
norm(v) ‖v‖
vec(AB) →AB (over-arrow vector)
floor(x) ceil(x) ⌊x⌋ ⌈x⌉ (integer part)
bar(z), conj(z) z̄ (conjugate, mean, closure)
not(A cup B) (A∪B)‾ (logical negation, same overline)
lim(x->0) f(x) limit, -> becomes the arrow, target under the word
partial, nabla ∂, ∇ (use (partial f)/(partial x) for ∂f/∂x)
pi, alpha, … Greek letters
inf

The helpers nest, so the secondary-school staples come for free: norm(vec(AB)) is the norm of a vector, vec(AB) + vec(BC) = vec(AC) is Chasles' relation.

Sets, logic and relations

From collège to the upper years a worksheet needs the standard notation. It is carried as plain words and ASCII shortcuts, so a statement reads as one types it.

Number sets — a doubled capital gives the blackboard-bold set (the ASCIIMath convention). Doubling avoids any clash with a one-letter variable:

You write You get
NN ZZ DD QQ RR CC ℕ ℤ 𝔻 ℚ ℝ ℂ
PP KK HH FF EE UU ℙ 𝕂 ℍ 𝔽 𝔼 𝕌 (advanced)

Quantifiers and logicforall ∀, exists ∃; connectives and ∧, or ∨, lnot ¬, neg ¬. Implication and equivalence come both as words and as arrows: => or implies ⇒, <=> or iff ⇔ (inside a formula; in running prose double the chevrons as <<=>>). The longer arrow forms win over the comparison they contain, so abs(x) <= 1 <=> -1 <= x <= 1 parses correctly.

Negation — one rule: ! before a relation or quantifier negates it, picking the proper struck-through glyph. So !in is ∉, !exists is ∄, !subset is ⊄, !subseteq is ⊈, !equiv is ≢. (!= stays "not equal", ≠.)

Set relationsin ∈, subset ⊂, supset ⊃, subseteq ⊆, supseteq ⊇, cup ∪, cap ∩, setminus ∖, emptyset ∅ (negate any with !).

Arrows-> or to →, mapsto ↦.

$forall epsilon > 0, exists eta > 0$
$x in RR setminus QQ$
$x !in QQ$
$(P and Q) => P$

Brackets and accents

The integer part and a few one-argument wrappers follow the same name(...) shape as abs and vec: floor(x) ⌊x⌋, ceil(x) ⌈x⌉, set(x : x > 0) a brace set, abr(u, v) ⟨u, v⟩ an inner product.

An overline is named by intent — the same rule under two words: bar(...) for the generic bar (complex conjugate, mean, closure of a set) and not(...) for logical negation, so bar(z) is z̄ and not(A cup B) is (A∪B)‾. The usual accents complete the set: hat(f), tilde(x).

Limits with an arrow

lim(x->0) f(x) already sets a limit with its target under the word. For the running phrase "uₙ tends to ℓ" written over an arrow, use arrow(...): u_n arrow(n to +inf) l sets a long right arrow with the condition underneath. to and -> are interchangeable inside it.

$lim(n -> +inf) u_n = l$
$u_n arrow(n to +inf) l$

Operators with an index: sum, prod, lim

sum, prod and lim carry their index in (...) and set their whole expression in display style, so a fraction in the body keeps full size and a limit's target sits under the word, as on a blackboard. The body runs to the end of the formula or to the first =:

$sum(i=1, n) i = n(n+1)/2$
$prod(k=1, n) k$
$lim(x->0) sin(x)/x = 1$
$lim(x->+inf) 1/x$

Functions and trigonometry

Function names are set upright automatically — no backslashes. The set covers sin cos tan cot sec csc, the inverses arcsin arccos arctan, the hyperbolics sinh cosh tanh coth, and ln log exp det dim gcd deg ker arg max min sup. A name glued to (...) takes its argument as one atom, so fractions and powers behave:

$sin(x)^2 + cos(x)^2 = 1$
$cos(a+b) = cos(a)cos(b) - sin(a)sin(b)$
$tan(x) = sin(x)/cos(x)$

Integrals

The integral family writes its variable and bounds in the head (...) and captures the integrand as its body; the differential \,dx is appended automatically. No bounds gives a primitive, a comma-separated pair a definite integral:

$int(x) f(x)$              ∫ f(x) dx
$int(x=a, b) f(x)$         ∫ from a to b of f(x) dx

Multiple integrals — separate several domains with ;. The count of domains chooses ∫, ∬ or ∭; the differentials come out in reverse order (Fubini):

$int(x=a, b ; y=c, d) f(x,y)$            ∬ … dy dx
$int(x=a, b ; y=c, d ; z=e, g) f$        ∭ … dz dy dx

A single named domain is a region integral: int(D) f gives ∬D f dω. Named integrals: contourint(C) f(z) is a contour integral ∮, pvint(x=a, b) f(x) a Cauchy principal value, meanint(x=a, b) f(x) the average integral ⨍.

Derivatives

A Leibniz derivative is written as the fraction it is, and the differential d is set upright (ISO 80000-2), matching the d of the integrals — only when both sides of the fraction carry it, so a variable named d is never disturbed (d/2 stays the fraction d over 2):

$dy/dx$                 dy/dx, upright d
$(d^2 y)/(dx^2)$        second derivative
$dy/dx + y = 0$         a differential equation

Partial derivatives use partial (∂); parenthesise each side so the fraction groups correctly:

$(partial f)/(partial x)$
$(partial u)/(partial t) = (partial^2 u)/(partial x^2)$

nabla (∇) is available for gradients and divergences.

Maths blocks

Matrices and systems are blocks: one line is one row, and inside a matrix ; separates the entries. Every cell still goes through the mini-language.

<matrix>{
1 ; 2 ; 3
4 ; 5 ; 6
}

<matrix> draws parentheses, <det> the bars of a determinant, <bmatrix> square brackets. A single | inside a row draws the bar of an augmented matrix (allowed on matrix and bmatrix, never on det). A <system> stacks equations under a brace, aligned on the first relational operator:

<system>{
2x + 3y = 7
x - y = 1
}

Inject a computed value with #{expr} (or #name), including inside maths: $#k^2$. Decimal numbers follow the lang option.

The expression computes with a full function library. Inside #{...} you have the transcendental functions, in radians by default:

  • circular sin cos tan cot sec csc and their inverses arcsin arccos arctan; the degree variants sind cosd tand and arcsind arccosd arctand take or return degrees, so #{sind(30)} is 0.5 and #{arcsind(0.5)} is 30;
  • hyperbolic sinh cosh tanh coth sech csch and inverses arcsinh arccosh arctanh;
  • exponential and logarithms exp, ln (natural), log (base 10), log2, logb(v, b) (base b);
  • algebraic and rounding sqrt cbrt abs sign min max floor ceil and round(x, d) (to d decimals, ties away from zero), with the constants pi and e.

So #{sin(pi/6)}, #{exp(1)}, #{logb(81, 3)} all evaluate. The same library backs <plot>, so a curve of cosh(x) or arctan(x) draws from the identical definition.

Rounding for display: precision. The class option precision:N rounds every computed #{...} value to N decimals, dropping trailing zeros (3.50 prints 3.5, 4.0 prints 4). The default -1 prints the number as computed. precision sets the document-wide default; round(x, d) overrides it locally in any single expression. So precision:2 turns #{1/3} into 0.33 while #{round(1/3, 5)} still gives 0.33333.

Advanced vocabulary

For the upper years, the mini-language carries the named notation of probability, linear algebra and vector analysis. Each entry keeps the name(...) shape, and the rendering is the canonical a textbook uses.

Counting and probability — the binomial coefficient and arrangement are recognised by their two arguments, so a one-argument C(t) stays an ordinary function. Probability and expectation are the doubled blackboard letters, with the conditional bar written mid:

You write You get
C(n, k) binomial coefficient ⁽ⁿₖ⁾
A(n, k) arrangement Aₙᵏ
factorial(n) or n! n!
PP(A), PP(A mid B) ℙ(A), ℙ(A ∣ B)
EE(X) 𝔼(X)
var(X) std(X) cov(X, Y) Var(X), σ(X), Cov(X, Y)
normal(mu, sigma) 𝒩(μ, σ²)
poisson(lambda) 𝒫(λ)
binomial(n, p) ℬ(n, p)
repart(X, x) densite(X, x) F_X(x), f_X(x)

Linear algebra — named operators on top of the matrix blocks:

You write You get
ker(f) im(f) rank(A) Ker(f), Im(f), rg(A)
span(u, v) tr(A) com(A) Span(u, v), tr(A), com(A)
transpose(A) inv(A) Aᵀ, A⁻¹
eigen(A) adj(A) Sp(A) (spectrum), adj(A)

Vector analysis and transforms — the differential operators, the Landau notations (spelt out so the letters o/O stay free), and the integral transforms:

You write You get
grad(f) div(F) curl(F) grad f, div F, rot F
lap(f) Δf (prefixes its operand, no parentheses)
dirderiv(f, u) ∇_u f
bigO(...) litO(...) O(·), o(·)
laplace(f) fourier(f) ℒ{f}, ℱ{f}
ilaplace(f) ifourier(f) ℒ⁻¹{f}, ℱ⁻¹{f}
surfint(S) volint(V) flux(F, S) ∯_S, ∭_V, a flux

Arithmetic, number theory and sets — and a few calculation templates:

You write You get
lcm(a, b) gcd(a, b) sign(x) lcm, gcd, sgn
card(A) powerset(A) card(A), 𝒫(A)
range(1, n) ⟦1, n⟧ (integer interval)
set(x mid x > 0) {x ∣ x > 0} (the keyword mid spaces the bar)
euler(n) mobius(n) φ(n), μ(n)
a equiv b mod n a ≡ b (mod n)
taylor(f, x, a, n) the Taylor form (template)
jacobian(f, n) hessian(f, n) the generic partial-derivative matrices
$EE(X) = sum(k=1, n) k PP(X = k)$
$var(X) = EE(X^2) - EE(X)^2$
$dim(ker(f)) + rank(f) = dim(E)$
$lap(f) = div(grad(f))$
$flux(F, S) = volint(V) div(F)$

Function studies

Three tags turn a function into a variation table and a curve. They share one source of truth: a function object built once with <fn>, then read by <vartab> (the table) and <plot> (the graph).

The function object: <fn>

The equation form reads as the board does and registers itself under its left-hand name — the variable is declared in situ, and a study is then three lines that read like the exercise:

<fn f(x) = (x+2)(x-3)>
<signtab f>
<plot f x:{-4, 5}>

Table attributes stay attributes after the expression:

<fn g(t) = t^2 - 2t
    x:{-inf | 1 | +inf}
    deriv:{- | +}
    var:{+inf \ -1 / +inf}>

A tabular-only object (a table without a formula) takes the head without =<fn v(x) x:{...} deriv:{...} var:{...}>. Objects rebind sequentially: a later <fn f(x) = ...> shadows the name for what follows, never for what precedes — each <signtab f> or <plot f> sees the definition above it. The 2.4 name:/expr: attributes still parse but are deprecated; the equation form is the canonical one:

let k = <fn name:{k(x)}
            expr:{(x^2+1)/(x-1)}
            x:{-inf | 1-sqrt(2) | 1 | 1+sqrt(2) | +inf}
            second:{- | - || + | +}
            deriv:{+ | - || - | +}
            var:{-inf / 2-2sqrt(2) \ -inf || +inf \ 2+2sqrt(2) / +inf}>

let NAME = <fn …> stores the object under NAME (the assignment may span several lines, up to the closing >). Fields:

  • name:{k(x)} — the function and its variable; sets the row labels x, k'(x), k(x) (and k''(x) when a second-derivative line shows). name:{k} alone uses x; omit name: for f(x).
  • expr:{…} — the formula, in the maths mini-language. Read only by <plot>; <vartab> ignores it.
  • x:{… | … | …} — the remarkable abscissas, separated by |.
  • deriv:{…} — the sign of the first derivative, one sign per interval.
  • second:{…} — the sign of the second derivative (convexity), one per interval. Optional.
  • var:{…} — the variation line (see below).

The table: <vartab>

<vartab k> reads the object k. Or write the data inline: <vartab x:{…} deriv:{…} var:{…}>.

Four shapes are allowed, depending on which sign lines you give. Only x: and var: are required; deriv: and second: are each optional:

shape fields rows
full study second: + deriv: x, f″(x), f′(x), f(x)
classic variation deriv: x, f′(x), f(x)
convexity only second: x, f″(x), f(x)
value table neither x, f(x)

f″ always sits above f′. The value table (no sign line) just joins the listed values by arrows.

Sign lines (deriv:, second:) take one sign per interval: +, -, or empty. || (a double bar) marks a forbidden value (a pole): the bar crosses every row. Zeros at sign changes are placed automatically — you don't write them.

The variation line (var:) alternates value and connector. A connector is / (rising) or \ (falling), surrounded by spaces — glued, as in 2/3, it is a fraction, not an arrow. || carries the two limits around a pole. Values may be numbers, +inf/-inf, or any maths expression (2-2sqrt(2), 27/4).

Rules the table enforces: a value between two arrows of the same direction is rejected — a variation table lists only bounds and extrema, never a point on a monotone branch (that point belongs on the plot). When f″ and f′ show together, x: must list the union of their zeros, since all rows share the same columns.

The sign table: <signtab>

The companion of <vartab> for factored expressions. Automatic: the rows are computed from a product/quotient of affine factors — exact rational zeros, a forbidden value at each denominator zero, even multiplicities known not to change sign:

<fn f(x) = (x+2)(x-3)>
<signtab f>

<fn g(x) = (x+1)/(x-2)>
<signtab g>

<fn h(x) = -2(x+1)^2 (x - 1/2)>
<signtab h>

Manual (the general form, for rows the affine engine cannot derive) — one row per factor, usually a conclusion row last:

<signtab x:{-inf | -2 | 3 | +inf}>{
    x+2  : - | 0 | + | +
    x-3  : - | - | 0 | +
    f(x) : + | 0 | - | 0 | +
}

A cell is a sign per interval; a 0 marks a zero at the boundary it follows, || a forbidden value. The invariant is checked at compile time: a row that changes sign without a 0 or a || at the boundary is an error, not a wrong table in print — an expression cannot change sign without vanishing or ceasing to exist there.

The graph: <plot>

<plot k samples:200 x:{-4, 6} y:{-10, 12}>

<plot k> reads expr: and name: from the object. Options:

  • x:{a, b} — horizontal display window (comma between the two bounds). Defaults to the finite abscissas of the table.
  • y:{c, d} — vertical window. Required when the function runs to infinity (a pole), so the view is framed.
  • samples:N — number of points computed (default 100).

expr: is translated to the plotter's syntax: the variable becomes the plotting variable, trigonometric calls get the degree conversion, and implicit products (2x, 2(x-1)) become explicit. Poles are handled so no spurious vertical line joins the branches. Supported in expr:: + - * / ^, parentheses, sin cos tan exp ln log sqrt abs, and pi.

<vartab> is declarative, <plot> is computed. If var: does not match expr:, the table and the curve contradict each other silently — keeping them consistent is yours to ensure.

Areas. area:{a,b} shades the region between the curve and the x-axis on a, b, with dashed verticals at the bounds; between:g shades between two curves instead (clipped to area: when given):

<plot f x:{-1, 4} area:{1, 3}>
<plot f x:{-1, 4} between:g area:{0, 3}>

Sequences: the cobweb. cobweb:{u0} (or cobweb:{u0, n}, default n = 8) draws the bisector y = x and the staircase of u(n+1) = f(u(n)); the iterates are computed at compile time and the first three labelled on the axis:

let h = <fn name:{h(x)} expr:{sqrt(2x+3)}>
<plot h x:{0, 4} y:{0, 4} cobweb:{0.2, 10}>

Probability laws. The two laws of the lycée need no <fn> object; area: highlights P(a ≤ X ≤ b) on both — shaded under the Gaussian, stronger bars on the binomial. The normal window defaults to μ ± 4σ; the binomial masses are computed exactly:

<plot normal:{0, 1} area:{-1, 1.5}>
<plot binomial:{12, 0.4} area:{3, 6}>
Maths note: in prose use the mini-language spellings !=, +-, >=, <= (not \neq, \pm, …). Write $f(x)$ to typeset a formula; an unbracketed f(x)/x parses as f times (x)/x, so phrase it as "the ratio of $f(x)$ to $x$".

The lycée toolbox

Five more figures complete the secondary curriculum (2.5).

The weighted probability tree<tree>, the most-drawn object of première and terminale. Each line reads LABEL PROBABILITY, an optional brace opening the children; a leading ! is the complementary event (overline). Probabilities may be numbers or symbols (p, 1-p). A node with exactly one branch receives its complement automatically — the only case that is mathematically determined; siblings that sum to something other than 1 are a compile error. products:on writes P(A ∩ B) = 0.18 at each leaf — the exact product when numeric, the symbolic chain otherwise. The layout is computed: leaves evenly spaced, nodes at the mean height of their children.

<tree products:on>{
    A 0.3 {
        B 0.6
    }
    !A 0.7 {
        B 0.1
    }
}

Descriptive statistics — one tag, <stats>, five kind:s, every number computed at compile time:

<stats kind:bars data:{1: 4 | 2: 7 | 3: 2}>
<stats kind:bars data:{Walk: 5 | Bus: 3 | Bike: 2}>
<stats kind:histogram bounds:{0, 5, 10, 20} counts:{3, 7, 2}>
<stats kind:pie data:{Walk: 5 | Bus: 3 | Bike: 2}>
<stats kind:boxplot data:{12, 15, 9, 21, 14, 15, 18}>
<stats kind:scatter data:{(1, 2.1) (2, 2.6) (3, 3.4)} fit:on>

The dictionary key: value | … is the form of the mappings — bars (numeric keys give a numeric axis, words give categories) and pie; pairs (x, y) remain the form of the clouds, where an abscissa may repeat.

Data variables. A Lua table declared with let is passed by name — the natural home of data reused across figures:

let notes = {
    Mathematiques = 15.5,
    Francais = 12.0,
    Anglais = 18.0
}
<stats kind:bars data:notes>
<stats kind:pie data:notes>

A Lua table has no writing order, so map keys come out sorted (numbers numerically, words alphabetically); when the order matters, write a list of pairs, which keeps it: let trimestres = {{"T1", 11.5}, {"T2", 13.0}}. Lists of numbers feed boxplot, lists of {x, y} pairs feed scatter, and two list variables feed histogram through bounds: and counts:.

Three honesty guarantees, because a statistics figure teaches by its construction: the histogram draws density (count over class width), so unequal classes stay truthful; the boxplot uses the French secondary-school quartiles (Q1 the smallest value with at least a quarter of the data at or below it, Q3 likewise at three quarters); fit:on draws the least-squares line — computed, not eyeballed.

The number line<numberline>, the figure of inequalities and absolute values. Solved: the block form takes one inequality (the tag's braces cannot carry < and >) and computes the set exactly — an affine expression against a constant, a product/quotient of affine factors against 0, or abs(affine) against a constant. Strictness decides open/closed; a denominator zero is always excluded; an isolated solution is a point:

<numberline x:{-5, 5}>{
    abs(x - 1/2) >= 5/2
}

Declared, when the set is given rather than solved — brackets follow the international convention ([ ] included, ( ) excluded); a bound may be inf, the segment then runs to the arrow; points: pins isolated values:

<numberline x:{-5, 5} set:{[-2, 3) union (4, inf)} points:{-4}>

The trigonometric circle — one <draw> line: the circle, its axes, and the sixteen remarkable angles labelled by their principal measure in (−π, π]. values:on adds the dashed cos/sin projections (exact values at the remarkable angles, two decimals elsewhere). Dynamic: step:{pi/12} draws the multiples of the step, range:{0, pi/2} restricts to an arc — the first-quadrant close-up. Labels too crowded to read are a compile error suggesting a larger step:

<draw>trigcircle radius:4 values:on
<draw>trigcircle radius:4 step:{pi/6}
<draw>trigcircle radius:4 range:{0, pi/2} step:{pi/12} values:on

Space geometrysolid lines inside <draw> render the full repertoire in the French perspective cavalière (receding axis at 45°, ratio 0.5; override with angle:/ratio:). Hidden edges are computed, not declared: a face of a convex solid is visible exactly when the projection preserves its outward orientation, and an edge is dashed exactly when both of its faces are hidden. Several solids in one block sit side by side. Vertex names are optional on cube, cuboid (eight letters, base then top) and pyramid (apex first). Plane sections are deferred to a later release.

<draw>{
    solid cube ABCDEFGH edge:4
    solid pyramid SABCD base:4 height:5
}
<draw>{
    solid cuboid sides:{5, 3, 2}
    solid cylinder radius:1.5 height:4
    solid cone radius:2 height:4.5
    solid sphere radius:2.5
}

Boxes

<box line:Crimson fill:MistyRose radius:4 title:{A note}>{
Content here.
}

Options: line: frame colour, fill: background, text: text colour, radius:N rounded corners (mm), width:N or width:N%, boxrule:N, sep:N (inner padding, mm; boxsep:N is a synonym), break:yes, title:{…}, titlefill:, titletext:. A line containing only --- splits a box into two regions.

<row gap:N>{ … } lays its child boxes side by side, equal widths and equalised heights. A box also takes a two-letter placement code (tlbr, default tl); the vertical part needs a height: to act.


Grid (named-area layout)

For full-page layouts — a worksheet header with a logo, a title bar, info fields, and a body — <grid> borrows CSS Grid's named-area idea. A template:[ … ] of quoted rows draws the layout; each word names a cell. A name repeated horizontally spans columns, vertically spans rows; a dot . is empty.

<grid template:[
  "title  title  logo"
  "intro  info   logo"
  "body   body   body"
] gap:4>{
  <area title>{ <Red b 16pt>Maths assessment }
  <area logo >{ <img>{blason.png} }
  <area intro>{ Instructions: no calculator. }
  <area info >{ Name: \\ First name: }
  <area body >{ <s1>Exercise 1
    Solve the equation... }
}

An area can be framed like a box (line:, fill:, radius:, title:). The grid takes width: and height:; an area or the grid takes a two-letter placement code for content position within cells.


Lists

A list is <list:STYLE> — the style follows the name, one item per line, no item tag:

<list:decimal>{
Read the instructions
Underline the key words
Write your answer
}

Styles — bullets: none disc circle square; numbered: decimal alpha ALPHA roman ROMAN (the case of the keyword sets the case of the letters); checkboxes: check. A list written under an item becomes its sub-list, nested as deep as you like. Text attributes on the tag wrap the whole list: <list:ROMAN TIMES NEW ROMAN 12pt i>{ … }.


Block aliases

Define a reusable component once; #param placeholders are filled at the call site, and the call-site body becomes the block content — so it may contain sub-blocks of its own.

let card{title, frame} = <box title:{#title} line:#frame radius:2>

<card First, Crimson>{ Called with two arguments. }
<card Second, Navy>{ Same component, different look. }

Control flow

for n in 1..3 {
<c Navy b>Sheet #n
}

for f in [chat.png, chien.png] {
<img 16>{#f}
}

if score >= 10 {
<Green>Passed.
} else {
<Red>Try again.
}

Loops and conditions work in the document body, inside boxes, and inside table bodies. The loop variable interpolates everywhere via #.


Escapes

To print a character that scholatex treats specially, double it: << >> {{ }} ## give a literal < > { } #. The backslash is an ordinary character — a path like C:\Users\Leo or a regex \d+\s*\w prints verbatim, nothing to escape. The characters _ & % ~ are escaped automatically. A line break inside a paragraph is the tag <nextline>. A line whose first non-space character is % is a comment. A bare # not followed by a name or {…} is a literal #.

Braces carry structure, so a literal brace must be balanced: write the pair {{…}} to print {…}. A lone, unmatched {{ or }} is reported as an unbalanced brace naming its line, rather than silently corrupting the surrounding block — so set-builder notation like {{ x : x > 0 }} is written as a pair. Angle brackets and hashes need no such balancing; only braces do.


## Colour reference

Every colour is written in CamelCase — there is one rule and no lowercase shortcuts. The everyday colours are simply capitalised: Red Blue Green Navy Orange Purple Teal Brown Gray/Grey Pink Yellow Black White Violet Cyan Magenta Lime Olive Aqua Silver Maroon.

For the full palette, write any of the 151 CSS / svgnames colours in CamelCase (<SteelBlue>{…}, fill:MistyRose, line:DarkOrange). They are grouped below by family for browsing; all are valid anywhere a colour is expected (line: fill: text: and inline tags).

Reds & pinks (14) — Brown, Crimson, DarkRed, FireBrick, IndianRed, LightCoral, LightPink, Maroon, MistyRose, Pink, Red, RosyBrown, Salmon, Tomato

Oranges & browns (23) — AntiqueWhite, Bisque, BlanchedAlmond, BurlyWood, Chocolate, Coral, DarkGoldenrod, DarkOrange, DarkSalmon, Goldenrod, LightSalmon, Moccasin, NavajoWhite, Orange, OrangeRed, PapayaWhip, PeachPuff, Peru, SaddleBrown, SandyBrown, Sienna, Tan, Wheat

Yellows & golds (11) — Cornsilk, DarkKhaki, Gold, Khaki, LemonChiffon, LightGoldenrod, LightGoldenrodYellow, LightYellow, Olive, PaleGoldenrod, Yellow

Greens (20) — Aquamarine, Chartreuse, DarkGreen, DarkOliveGreen, DarkSeaGreen, ForestGreen, Green, GreenYellow, LawnGreen, LightGreen, Lime, LimeGreen, MediumAquamarine, MediumSeaGreen, MediumSpringGreen, OliveDrab, PaleGreen, SeaGreen, SpringGreen, YellowGreen

Cyans & teals (17) — Aqua, CadetBlue, Cyan, DarkCyan, DarkSlateGray, DarkSlateGrey, DarkTurquoise, DeepSkyBlue, LightBlue, LightCyan, LightSeaGreen, MediumTurquoise, PaleTurquoise, PowderBlue, SkyBlue, Teal, Turquoise

Blues (21) — Blue, CornflowerBlue, DarkBlue, DarkSlateBlue, DodgerBlue, LightSkyBlue, LightSlateBlue, LightSlateGray, LightSlateGrey, LightSteelBlue, MediumBlue, MediumPurple, MediumSlateBlue, MidnightBlue, Navy, NavyBlue, RoyalBlue, SlateBlue, SlateGray, SlateGrey, SteelBlue

Purples & violets (17) — BlueViolet, DarkMagenta, DarkOrchid, DarkViolet, DeepPink, Fuchsia, HotPink, Indigo, Magenta, MediumOrchid, MediumVioletRed, Orchid, PaleVioletRed, Plum, Purple, Violet, VioletRed

Grays (10) — DarkGray, DarkGrey, DimGray, DimGrey, Gray, Grey, LightGray, LightGrey, Silver, Thistle

Whites & off-whites (17) — AliceBlue, Azure, Beige, FloralWhite, Gainsboro, GhostWhite, Honeydew, Ivory, Lavender, LavenderBlush, Linen, MintCream, OldLace, Seashell, Snow, White, WhiteSmoke

Black (1) — Black

These are exactly the colours xcolor provides under its svgnames option (the 147 CSS Color Module names plus the four X11 extras LightGoldenrod, LightSlateBlue, NavyBlue and VioletRed). Names are case-sensitive: write Seashell, not SeaShell.


## Security

scholatex evaluates let name = expr, #{expr} and the conditions of for/if/while as Lua at compile time, so by default a document can run arbitrary code — exactly like \directlua.

Setting untrusted=true in \documentclass[...]{scholatex} runs that Lua in a restricted environment: only pure, side-effect-free names are visible; os, io, package, require, load, debug and other escape vectors are absent. A blocked access stops the compile with a clear message; a runaway loop is aborted by an instruction-count ceiling; string.rep/string.format are capped.

\documentclass[untrusted=true]{scholatex}

untrusted hardens the scholatex expression layer only. It does not sandbox Lua as a whole — a hostile .tex can still call \directlua, \write18, \input. Use it when the scholatex body comes from a semi-trusted source while the surrounding .tex is your own; for a whole untrusted .tex, run lualatex without --shell-escape, ideally in a container.


Examples

The examples/ folder contains eight self-contained, fully commented documents that together exercise every feature:

File Covers
text-style.tex the case rule, styles, colours, fonts, sizes, alignment, tabs, skips, scripts; factoring styles into aliases; a table of contents from the heading keywords
containers.tex tables, boxes and the named-area grid, each built up from its simplest form to a full worksheet header
basics.tex the inline mini-language, number sets, quantifiers and connectives, negation with !, set relations, the integer part, the overline, and arithmetic helpers
analysis.tex operators with an index, limits, trigonometry, derivatives, the vector operators, the integral family, transforms — then sign tables, the number line, areas and cobwebs, and four full function studies (<fn>, <vartab>, <plot>), from polynomial to hyperbolic
algebra.tex the matrix / determinant / augmented-matrix / system blocks, and the linear-algebra vocabulary
geometry.tex angles, vectors, coordinate systems, the <draw> figures and axes — then the trigonometric circle and the six solids in cabinet projection
statistics-probability.tex counting, probability and expectation, variance, distributions and density — then weighted trees, the two laws, and the five figures of descriptive statistics

Compile any of them with lualatex <file>.tex from the examples/ folder.


Project layout

scholatex.cls            LaTeX class: options, packages, reads & injects the body
scholatex.lua            transpiler core: tags, text, control flow, aliases
scholatex-style.lua      attribute resolution (colours, styles, sizes, alignment…)
scholatex-math.lua       the $…$ math mini-language (operators, integrals, functions, trig)
scholatex-util.lua       parsing primitives (groups, brace balance, comma split)
scholatex-table.lua      the <table> block
scholatex-img.lua        the <img> tag
scholatex-box.lua        the <box> and <row> blocks
scholatex-grid.lua       the <grid> named-area layout block
scholatex-section.lua    the <section>/<subsection>/<subsubsection> blocks
scholatex-list.lua       the <list:STYLE> block
scholatex-matrix.lua     the <matrix>/<det>/<bmatrix> and <system> blocks
scholatex-vartab.lua     the <fn> object and the <vartab> table
scholatex-signtab.lua    the <signtab> sign table
scholatex-plot.lua       the <plot> curve: areas, cobwebs, probability laws
scholatex-tree.lua       the <tree> weighted probability tree
scholatex-stats.lua      the <stats> descriptive-statistics figures
scholatex-numberline.lua the <numberline> graduated line, declared or solved
scholatex-affine.lua     exact sign analysis of affine factors (rational zeros)
scholatex-figure.lua     the <draw> block: figures, points, segments, trigcircle
scholatex-solid.lua      space geometry in cabinet projection (solid …)
scholatex-toc.lua        the <tableofcontents> tag
examples/                eight commented showcase documents

New tags register themselves via scholatex.register_tag / scholatex.register_block; a name clash raises an error rather than silently overwriting, so modules stay independent.


Diagnostics

Errors point at the source line, e.g. scholatex: line 12: unknown tag attribute: 'xyz'. Defining an alias whose name is a built-in (let section = …) prints a warning: the built-in always wins, so the alias would be silently dead — pick a different name.


What's new

2.5

The lycée release: the last nine figures and tables of the French secondary curriculum, so a worksheet from seconde to terminale never leaves the tag language.

  • Sign tables <signtab> — automatic (<signtab f> computes rows, exact zeros and forbidden values from the factored expression) or manual (one row per factor, 0 at a boundary zero, || at a forbidden value; a sign change without either is a compile error).
  • Weighted probability trees <tree> — declarative branches, !B for the complement, symbolic probabilities accepted, single branches auto-completed with their complement, products:on for the leaf products (exact when numeric).
  • Areas in <plot>area:{a,b} under a curve, between:g between two curves.
  • Cobwebscobweb:{u0, n} draws the staircase of u(n+1) = f(u(n)) with the bisector, iterates computed.
  • Probability laws<plot normal:{mu,sigma}> and <plot binomial:{n,p}> without an <fn> object; area: highlights P(a ≤ X ≤ b) on both.
  • The <fn> equation form<fn f(x) = (x+2)(x-3)> registers itself under its left-hand name; the declaration reads like the exercise.
  • Data variableslet notes = {Mathematiques = 15.5, ...} then <stats kind:bars data:notes>; multi-line let tables accepted.
  • Statistics <stats> — bars (a dictionary of frequencies, numeric or categorical), histogram (density, honest with unequal classes), pie, boxplot (French quartiles), scatter with a computed least-squares fit:on.
  • Trigonometric circle<draw>trigcircle, remarkable angles in principal measure by default, step:{pi/12} and range:{0, pi/2} for a chosen graduation or a first-quadrant close-up, values:on for the cos/sin projections.
  • Number line <numberline> — declared interval sets (included/excluded endpoints, union, infinite bounds, isolated points) or a solved inequality (block form), the set computed exactly.
  • Space geometrysolid cube/cuboid/pyramid/cylinder/cone/sphere in perspective cavalière, hidden edges computed from face orientation, solids laid side by side.

2.4

  • Analytic geometry in <draw>: the axes: mode<draw axes:{xmin,xmax,ymin,ymax}> draws a graduated cartesian frame and reads every line as a coordinate directive rather than a construction. One unit stays one centimetre and the drawing is clipped to the window. A block without axes: keeps the 2.3 construction behaviour unchanged.
    • point NAME (x,y) places and labels a point, available to later lines by name.
    • vector u (x,y) draws a free vector from the origin; vector AB the bound vector between two placed points. A named vector is remembered: vector s = u+v (or u-v) draws the sum or difference, labelled with the expression along the arrow; from: moves any vector's tail (a placed point, a literal pair, or ~u for the tip of a drawn vector) and style: restyles the copy (style:dashed-gray, style:Blue) — the parallelogram and triangle rules read on a single frame.
    • line by equation (y = 2x-1, x = -3, the general 2x+3y = 6) or line through A B.
    • circle center:A radius:r (centre a placed point or a literal pair) or by equation circle x^2+y^2 = 4; a named circle carries a tangent to:C at:P at a point on it.
    • region shades the half-plane of a linear inequality (<, >), the boundary dashed.
  • Parametric and polar curves in <plot>: the kind: fieldkind:parametric reads expr:{x(t), y(t)} over t:{a, b}; kind:polar reads expr:{r(theta)} over theta:{a, b}, drawn as (r cos theta, r sin theta). Bounds accept pi. Conics follow from the parametrisation (ellipse {a cos(t), b sin(t)}, parabola {t, t^2}, hyperbola {a cosh(t), b sinh(t)}) — no separate conic directive. A <plot> without kind: is the function graph, unchanged.

2.3

  • Figure drawing: the <draw> block — a plane figure is described, not hand-placed. Name the shape and give its measurements; the coordinates are computed trigonometrically and emitted as hard numbers. One drawing unit is one centimetre, so side:5 draws a 5 cm side.
    • Triangles by any classical definition — equilateral, isosceles, right (right angle at the first point, or right:X), three sides sides:(a,b,c), two sides and the included angle sides:(a,b) angle:t, two angles and a side angles:(A,B) side:c, or three sides named one by one (AB:3 BC:4 CA:5).
    • Quadrilateralssquare, rectangle, rhombus, parallelogram, trapezoid, and kite (two pairs of adjacent equal sides, the rhombus being the case where both pairs are equal).
    • Regular polygons by name from the pentagon up (pentagon, hexagon, octagon), or polygon with as many points as given.
    • Circles by centre and radius:r or diameter:d (the radius optionally a placed segment, radius:AB); circle ABC is the circumscribed circle of three placed points, with inscribed for the incircle.
  • Coding and measurementmarks:on codes equal sides and right angles; measures:cm / measures:mm labels each side with its length. Both are opt-in. When a figure has two pairs of equal sides of different lengths (kite, rectangle, parallelogram), the pairs are told apart by their tick count — a single tick on one pair, a double tick on the other — so a kite never reads as a rhombus.
  • Composite figures — several figures in one block share their points; a figure repeating a point is grafted onto it, and a figure sharing an edge deduces that edge's length and is flipped to the far side so the pieces abut. A shared edge is labelled once and ticked once, not twice.
  • Multi-character point names — besides the glued single letters (triangle ABC), a parenthesised comma-separated list names multi-character points: triangle (O, A0, B0).
  • Loops, interpolation and rotation inside <draw> — the same for VARIABLE in FROM..TO { … } loops as the rest of the language; #k and #{expr} interpolate point names and measurements; rotate:θ turns a figure about its first point, scale:F multiplies every coordinate of the picture by F leaving the text size alone (default 1, any <draw> form), and labels:off hides the vertex names — enough to fan, rosette or step figures round a centre.
  • Low-level primitives point and linepoint(P) places a dot at coordinates declared with let P = {x, y}; line(A, B) draws a segment between two points (names or literal {x, y} pairs), taking measures: like a figure side. As each coordinate is an ordinary expression, a loop can compute endpoints — the building block for free-form drawings.
  • Examples — a new geometry showcase covers the inline geometry vocabulary and the full <draw> block.

2.2

  • Probability and statistics — the blackboard operators PP(...) ℙ and EE(...) 𝔼 (with PP(A mid B) for a conditional), spread (var, std, cov), distributions (normal, poisson, binomial), and the distribution/density functions (repart, densite).
  • Counting — the binomial coefficient C(n, k) and arrangement A(n, k), recognised by their two arguments so a one-argument C(t) stays a function; the factorial factorial(n) or n!.
  • Linear-algebra vocabularyker, im, rank, span, tr, com, eigen (the spectrum), adj, with transpose(A) → Aᵀ and inv(A) → A⁻¹.
  • Vector analysisgrad, div, curl, the Laplacian lap(f) Δf, the directional derivative dirderiv(f, u), the Landau notations bigO/litO, the transforms laplace/fourier and their inverses, and the surface/volume integrals surfint/volint/flux.
  • Number theory and helperseuler φ, mobius μ, congruence a equiv b mod n, plus lcm, sign, card, powerset, the integer interval range(1, n) ⟦1, n⟧, the keyword mid for a spaced bar, and the templates taylor, jacobian, hessian.
  • Fixes — a parenthesised group over a fraction now grows to full height ((a/b)^2); higher-order differentials d^2y/dx^2 set the upright d throughout; plot tick numbers stay readable where a curve crosses an axis, and the axis arrow clears the last graduation.
  • Examples by domain — the maths showcase now mirrors the manual's four categories: basics, algebra, analysis (which holds the function studies) and probability.

2.1

  • Mathematical vocabulary — number sets in blackboard bold (NN ZZ DD QQ RR CC, plus PP KK HH FF EE UU), quantifiers and connectives (forall exists and or lnot neg), implication and equivalence as words or arrows (=>/implies, <=>/iff), set relations (in subset cup cap setminus emptyset …), the integer part (floor ceil round), and accents (bar/conj for the conjugate-mean-closure overline, not for logical negation, hat tilde).
  • Negation with a single !! in front of a relation or quantifier negates it with the proper struck-through glyph: !in ∉, !exists ∄, !subset ⊄, !subseteq ⊈, !equiv ≢. != stays "not equal".
  • Limit arrowarrow(n to +inf) sets a long right arrow with its condition underneath, for the "uₙ → l" phrasing in running maths.
  • Colours are CamelCase only (breaking change) — the lowercase keywords (red, navy, …) are removed; write the CamelCase form (Red, Navy). One rule for all 151 colours. A lowercase colour now raises an error that names the CamelCase replacement.
  • Function studies — three new tags for analysis: <fn> builds a function object (name, formula, abscissas, derivative signs, variation), <vartab> renders its variation table, <plot> draws its curve (via pgfplots, with pole handling). The table comes in four shapes — full (f″, f′, f), classic (f′, f), convexity (f″, f), or a plain value table (f) — since the two derivative lines are independent and optional.
  • Section numbering stylesnum, roman, ROMAN, alpha, ALPHA set the counter style of a heading level on its own, with no inherited prefix; the default stays hierarchical.
  • Examples reorganised — the showcase set is now text-style, containers, math-language, math-analysis, math-algebra and functions (the old single 03-math is split by topic).

2.0

  • New escape rules (breaking change) — to print a special character, double it: << >> {{ }} ## give a literal < > { } #. A backslash is now an ordinary character (so C:\Users just works); it is no longer an escape. The old \< \> \{ \} \# forms no longer apply.
  • Line break is a tag (breaking change) — use <nextline> (in text and table cells) instead of the old \\. In running text a blank line already starts a new paragraph, so <nextline> is only for a break without a paragraph change.

1.2

  • Script/fraction precedence fix^ and _ now bind tighter than /, so x^2/y renders as the fraction of x^2 over y (and 1/i^2 as 1 over i^2), matching ordinary mathematical reading
  • Automatic spacing for tall lines — consecutive lines containing fractions or integrals no longer touch; inserts just enough air where needed, leaving ordinary text unchanged

1.1

  • Maths expansion — full integral family (int, multiple integrals with Fubini ordering, contourint, pvint, meanint), upright functions and trigonometry, Leibniz and partial derivatives with ISO 80000-2 upright differentials
  • Operators in display stylesum, prod, lim keep fractions full-size and place limits under the word
  • Full colour parity — all 151 xcolor svgnames colours recognised, grouped by family in the reference
  • Cross-platform install — documented tlmgr and manual paths for macOS, Linux and Windows

Acknowledgments

scholatex is built on excellent packages:


License

Copyright © 2026 Gérard Dubard.

scholatex is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3 (or later) as published by the Free Software Foundation. See the LICENSE file for the full text.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Herunterladen des vollständigen Inhalts dieses Pakets in einem Zip-Archiv (587.8k).

scholatex – A tag-based language for print-ready teaching worksheets, built on Lua

scholatex is a Lua document class for teachers who need print-ready worksheets without writing . The author writes a single .tex file in a compact, readable tag language; the class translates it to at compile time and produces output of full quality.

Paketscholatex
Hilfe
Fehlermeldungen
Repository
Version2.5
LizenzenGNU General Public License, version 3 or newer
Copyright2026 Gérard Dubard
BetreuerGérard Dubard
Enthalten inTeX Live als scholatex
MiKTeX als scholatex
ThemenMarkup
Lehre
Struc mkup
Klassen
...
Gästebuch Seiten-Struktur Impressum Autor kontaktieren