\NeedsTeXFormat{LaTeX2e} \ProvidesClass{scholatex}[2026-06-18 v1.0 A tag-based language for print-ready teaching worksheets] % scholatex --- a lightweight tag-based markup language for LuaLaTeX % Copyright (C) 2026 Gerard Dubard % % This program is free software: you can redistribute it and/or modify it % under the terms of the GNU General Public License version 3 as published % by the Free Software Foundation. This program is distributed WITHOUT ANY % WARRANTY. See the LICENSE file or for % the full text of the license. % \RequirePackage{kvoptions} \SetupKeyvalOptions{family=scholatex, prefix=scholatex@} \DeclareStringOption[20]{margins} \DeclareStringOption[Latin Modern Roman]{font} \DeclareStringOption[11]{size} \DeclareStringOption[Latin Modern Math]{mathfont} \DeclareStringOption[img]{imgdir} \DeclareStringOption[8]{tabwidth} \DeclareStringOption[8]{lineheight} \DeclareStringOption[100]{scriptscale} \DeclareStringOption[2]{padding} \DeclareStringOption[fr]{lang} \DeclareBoolOption[false]{untrusted} \DeclareDefaultOption{\PassOptionsToClass{\CurrentOption}{extarticle}} \ProcessKeyvalOptions* \LoadClass[\scholatex@size pt, a4paper]{extarticle} \RequirePackage{amsmath} \RequirePackage{array} \RequirePackage{graphicx} \RequirePackage[export]{adjustbox} \RequirePackage{xstring} \IfEndWith{\scholatex@imgdir}{/}{% \edef\scholatex@imgpath{\scholatex@imgdir}% }{% \edef\scholatex@imgpath{\scholatex@imgdir/}% } \def\scholatex@graphicspaths{{./}} \@for\scholatex@dir:=\scholatex@imgdir\do{% \StrDel{\scholatex@dir}{ }[\scholatex@dir]% \IfEndWith{\scholatex@dir}{/}{% \edef\scholatex@graphicspaths{\scholatex@graphicspaths{\scholatex@dir}}% }{% \edef\scholatex@graphicspaths{\scholatex@graphicspaths{\scholatex@dir/}}% }% } \expandafter\graphicspath\expandafter{\scholatex@graphicspaths} \RequirePackage{tabularx} \RequirePackage{tabularray} \RequirePackage{multirow} \RequirePackage[svgnames]{xcolor} \RequirePackage{colortbl} \RequirePackage{enumitem} \RequirePackage{amssymb} \RequirePackage{ragged2e} \RequirePackage{needspace} \RequirePackage[skins,breakable,raster]{tcolorbox} \tcbuselibrary{poster} \setlength{\JustifyingParindent}{0pt} \newlength{\scholatextab} \setlength{\scholatextab}{\scholatex@tabwidth mm} \newlength{\scholatexline} \setlength{\scholatexline}{\scholatex@lineheight mm} % Headings carry no extra space above or below: only the normal interline % spacing separates them from surrounding text, identical for every level. % Their appearance (colour, size, a preceding line skip) is set per document % with a style alias, e.g. let s1 = . \RequirePackage{titlesec} \titlespacing*{\section} {0pt}{0pt}{0pt} \titlespacing*{\subsection} {0pt}{0pt}{0pt} \titlespacing*{\subsubsection}{0pt}{0pt}{0pt} \edef\scholatex@scriptfactor{\strip@pt\dimexpr\scholatex@scriptscale pt/100\relax} \newcommand{\scholatexscript}[2]{\raisebox{#1}{\scalebox{\scholatex@scriptfactor}{#2}}} \RequirePackage{fontspec} \RequirePackage{unicode-math} \RequirePackage{geometry} \StrCount{\scholatex@margins}{,}[\scholatex@ncommas] \ifnum\scholatex@ncommas>0\relax \StrCut{\scholatex@margins}{,}\scholatex@mt\scholatex@mrest \StrCut{\scholatex@mrest}{,}\scholatex@mr\scholatex@mrest \StrCut{\scholatex@mrest}{,}\scholatex@mb\scholatex@ml \geometry{top=\scholatex@mt mm, right=\scholatex@mr mm, bottom=\scholatex@mb mm, left=\scholatex@ml mm}% \else \geometry{margin=\scholatex@margins mm}% \fi % Short lowercase colour keywords: aliases to the CamelCase svgnames \colorlet{navy}{Navy} \colorlet{blue}{Blue} \colorlet{red}{Red} \colorlet{green}{Green} \colorlet{gray}{Gray} \colorlet{grey}{Grey} \colorlet{violet}{Violet} \colorlet{orange}{Orange} \colorlet{purple}{Purple} \colorlet{teal}{Teal} \colorlet{brown}{Brown} \colorlet{yellow}{Yellow} \colorlet{black}{Black} \colorlet{white}{White} \colorlet{pink}{Pink} \colorlet{olive}{Olive} \colorlet{lime}{Lime} \colorlet{aqua}{Aqua} \colorlet{cyan}{Cyan} \colorlet{magenta}{Magenta} \colorlet{silver}{Silver} \colorlet{maroon}{Maroon} \directlua{scholatex = require("scholatex")} \directlua{scholatex.config = scholatex.config or {}; scholatex.config.padding = "\scholatex@padding"; scholatex.config.lang = "\scholatex@lang"} \ifscholatex@untrusted \directlua{scholatex.config.untrusted = true} \else \directlua{scholatex.config.untrusted = false} \fi \IfFontExistsTF{\scholatex@font}{% \setmainfont{\scholatex@font}% }{% \directlua{scholatex.respace("scholatex@font")}% \IfFontExistsTF{\scholatex@font}{% \setmainfont{\scholatex@font}% }{% \ClassWarningNoLine{scholatex}{Font '\scholatex@font' not found, falling back to Latin Modern Roman}% \setmainfont{Latin Modern Roman}% }% } \IfFontExistsTF{\scholatex@mathfont}{% \setmathfont{\scholatex@mathfont}% }{% \directlua{scholatex.respace("scholatex@mathfont")}% \IfFontExistsTF{\scholatex@mathfont}{% \setmathfont{\scholatex@mathfont}% }{% \ClassWarningNoLine{scholatex}{Math font '\scholatex@mathfont' not found, falling back to Latin Modern Math}% \setmathfont{Latin Modern Math}% }% } \setlength{\parindent}{0pt} \setlength{\parskip}{0.5em} \AtBeginDocument{% \directlua{ local f = io.open(tex.jobname .. ".tex", "r") local whole = f:read("*a"); f:close() local body = whole:match("\string\\begin{document}(.-)\string\\end{document}") if not body then tex.error("scholatex.cls: begin/end document not found") else scholatex.inject(body) end }% \end{document}% }