summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/moodle/moodle.sty
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/latex/moodle/moodle.sty')
-rw-r--r--Master/texmf-dist/tex/latex/moodle/moodle.sty2368
1 files changed, 2036 insertions, 332 deletions
diff --git a/Master/texmf-dist/tex/latex/moodle/moodle.sty b/Master/texmf-dist/tex/latex/moodle/moodle.sty
index dedc78c95c9..3061bd3299d 100644
--- a/Master/texmf-dist/tex/latex/moodle/moodle.sty
+++ b/Master/texmf-dist/tex/latex/moodle/moodle.sty
@@ -8,7 +8,8 @@
%%
%% This is a generated file.
%%
-%% Copyright (C) 2016 by Anders Hendrickson <anders.hendrickson@snc.edu>
+%% Copyright 2016 by Anders O.F. Hendrickson (anders.o.f.hendrickson AT gmail.com)
+%% and 2019-2021 by Matthieu Guerquin-Kern (guerquin-kern AT crans.org).
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
@@ -20,36 +21,78 @@
%%
\NeedsTeXFormat{LaTeX2e}[1999/12/01]
\ProvidesPackage{moodle}
- [2016/01/11 v0.5 Moodle quiz XML generation]
+ [2021/01/04 v0.8 Moodle quiz XML generation]
\newif\ifmoodle@draftmode
+\newif\ifmoodle@handout
+\newif\ifmoodle@stampmode
+\newif\ifmoodle@tikz
\newif\ifmoodle@tikzloaded
+\newif\ifmoodle@svg
+\newif\ifmoodle@section
+\newif\ifmoodle@subsection
+\newif\ifmoodle@numbered
%%DECLARATION OF OPTIONS
\DeclareOption{draft}{\moodle@draftmodetrue}
+\DeclareOption{handout}{\moodle@handouttrue}
+\DeclareOption{final}{\moodle@draftmodefalse}
+\DeclareOption{nostamp}{\moodle@stampmodefalse}
+\DeclareOption{tikz}{\moodle@tikztrue}
+\DeclareOption{svg}{\moodle@svgtrue}
+\DeclareOption{section}{\moodle@sectiontrue\moodle@numberedtrue}
+\DeclareOption{section*}{\moodle@sectiontrue\moodle@numberedfalse}
+\DeclareOption{subsection}{\moodle@sectionfalse\moodle@numberedtrue}
+\DeclareOption{subsection*}{\moodle@sectionfalse\moodle@numberedfalse}
\moodle@draftmodefalse
+\moodle@handoutfalse
+\moodle@stampmodetrue
+\moodle@tikzfalse
\moodle@tikzloadedfalse
+\moodle@svgfalse
+\moodle@subsectiontrue
+\moodle@numberedfalse
\ProcessOptions
\RequirePackage{environ} %To be able to take environment body as a macro argument
\RequirePackage{xkeyval} %For key-handling
\RequirePackage{amssymb} %For \checkmark symbol
-\RequirePackage{trimspaces} %To remove extra spaces from strings
\RequirePackage{etex} %Expansion control, detokenization, etc.
\RequirePackage{etoolbox}%List management
\RequirePackage{xpatch} %To patch commands easily in HTML mode
\RequirePackage{array} %For formatting tables in the LaTeX mode of Clozes
\RequirePackage{ifplatform} % To choose Ghostscript commands
-\RequirePackage{ifpdf} % Needed to know whether we can convert output from PDF to PNG
-
+\@ifpackageloaded{iftex}{}{\RequirePackage{iftex}}
+\@ifundefined{ifpdf}{\RequirePackage{ifpdf}}{}% old iftex would not define the conditional
+\RequirePackage{shellesc} %Luatex-compatible way of getting system access
+\RequirePackage{fancybox} %For fancy LaTeX tags
\RequirePackage{getitems} %To gather the header and items
+\ifmoodle@handout
+ \RequirePackage[seed=42]{randomlist} %To randomize answers in matching questions
+\fi
+\ifmoodle@svg
+ \RequirePackage{graphicx} %To include graphics
+\fi
\let\xa=\expandafter
\def\@star{*}%
\def\@hundred{100}%
+\def\@fifty{50}%
\def\@moodle@empty{}%
\def\@relax{\relax}%
+\def\@moodle@par{\par}%
+
+\@ifundefined{ifTUTeX}{
+ \newif\ifTUTeX % a new conditional starts as false
+ \ifnum 0\ifXeTeX 1\fi\ifLuaTeX 1\fi>0%
+ \TUTeXtrue
+ \fi
+}{}%
+\newif\ifpdfoutput % a new conditional starts as false
+\ifnum 0\ifTUTeX 1\fi\ifPDFTeX\ifpdf 1\fi\fi>0%
+ \pdfoutputtrue
+\fi
\def\jobnamewithsuffixtomacro#1#2{%
\filenamewithsuffixtomacro{#1}{\jobname}{#2}%
}
@@ -78,9 +121,42 @@
\newwrite\moodle@outfile
\def\openmoodleout{%
\immediate\openout\moodle@outfile=\outputfilename\relax
- \writetomoodle{<?xml version="1.0" encoding="UTF-8"?>}%
+ \ifPDFTeX % latin1-based engines (pdflatex or latex)
+ \writetomoodle{<?xml version="1.0" encoding="iso-8859-1"?>}%
+ \else
+ \ifTUTeX % UTF8-based engines (XeTeX or LuaTeX)
+ \writetomoodle{<?xml version="1.0" encoding="UTF-8"?>}%
+ \else % what shall we do?
+ \writetomoodle{<?xml version="1.0" encoding="UTF-8"?>}%
+ %\stop
+ \fi
+ \fi
+ \ifmoodle@stampmode
+ \def\moodle@stamp{This file was generated on \the\year-\two@digits\month-\two@digits\day}
+ \ifPDFTeX % pdflatex or latex
+ \ifpdf % pdflatex
+ \g@addto@macro{\moodle@stamp}{ by pdfLaTeX }%
+ \else % latex
+ \g@addto@macro{\moodle@stamp}{ by LaTeX }%
+ \fi
+ \else
+ \ifXeTeX % xetex
+ \g@addto@macro{\moodle@stamp}{ by XeLaTeX }%
+ \else
+ \ifLuaTeX % luatex
+ \g@addto@macro{\moodle@stamp}{ by LuaLaTeX }%
+ \else
+ \g@addto@macro{\moodle@stamp}{ a TeX engine }%
+ \fi
+ \fi
+ \fi
+ \writetomoodle{<!-- \moodle@stamp -->}%
+ \def\moodle@stamp{running on \platformname}%
+ \g@addto@macro{\moodle@stamp}{ with the package moodle v0.8 }%
+ \writetomoodle{<!-- \moodle@stamp -->}%
+ \fi
+ \immediate\write\moodle@outfile{}%
\writetomoodle{<quiz>}%
- \writetomoodle{ }%
}%
\def\closemoodleout{%
\writetomoodle{ }%
@@ -111,27 +187,71 @@
\immediate\write\moodle@outfile{\moodle@indent\trim@pre@space{\test@ii}}%
\fi
}%
-\newenvironment{quiz}[2][]%
- {\setkeys{moodle}{#1}%
- \@moodle@ifgeneratexml{%
- \openmoodleout%
- \setcategory{#2}%
- }{}%
- \subsection*{#2}%
- \begin{enumerate}%
- }
- {\end{enumerate}%
- \@moodle@ifgeneratexml{\closemoodleout}{}}
-
-{\catcode`\$=12\catcode`\ =12%
-\gdef\setcategory#1{%
+{\catcode`\$=12\catcode`\ =12% in this context we cannot indent with spaces...
+\gdef\moodle@write@category@xml#1{%
+\@moodle@ifgeneratexml{%
+\writetomoodle{ }%
\writetomoodle{<question type="category">}%
\writetomoodle{ <category>}%
-\writetomoodle{ <text>$module$/#1</text>}%
+\writetomoodle{ <text>$course$/top/#1</text>}%
\writetomoodle{ </category>}%
\writetomoodle{</question>}%
\writetomoodle{ }%
+}{}%
}}%
+\newcommand*\@enumeratename{enumerate}%
+\newenvironment{quiz}[2][]{%
+ \setkeys{moodle}{#1}%
+ \gdef\setcategory##1{%
+ % At first call (end of \begin{quiz}) enumerate is not started yet
+ \ifx\@currenvir\@enumeratename
+ % In case no question is defined between two calls of \setcategory
+ \def\@noitemerr{\@latex@warning{Empty question list}}%
+ \end{enumerate}%
+ \fi
+ \gdef\moodle@currentcategory{##1}%
+ \moodle@write@category@xml{##1}%
+ \ifmoodle@section
+ \ifmoodle@numbered
+ \section{##1}%
+ \else
+ \section*{##1}%
+ \fi
+ \else
+ \ifmoodle@numbered
+ \subsection{##1}%
+ \else
+ \subsection*{##1}%
+ \fi
+ \fi
+ \begin{enumerate}%
+ }%
+ \gdef\setsubcategory##1{%
+ \def\@noitemerr{\@latex@warning{Empty question list}}%
+ \end{enumerate}%
+ \moodle@write@category@xml{\moodle@currentcategory/##1}%
+ \ifmoodle@section
+ \ifmoodle@numbered
+ \subsection{##1}%
+ \else
+ \subsection*{##1}%
+ \fi
+ \else
+ \ifmoodle@numbered
+ \subsubsection{##1}%
+ \else
+ \subsubsection*{##1}%
+ \fi
+ \fi
+ \begin{enumerate}%
+ }%
+ \setcategory{#2}%
+}{%
+ \end{enumerate}%
+ \let\setcategory\relax
+ \let\setsubcategory\relax
+}%
+
\def\passvalueaftergroup#1{%
\xa\xa\xa\gdef\xa\xa\csname moodle@remember@\string#1\endcsname\xa{\xa\def\xa#1\xa{#1}}%
\xa\aftergroup\csname moodle@remember@\string#1\endcsname
@@ -152,6 +272,16 @@
\fi
}%
}
+\AfterEndPreamble{
+ \@moodle@ifgeneratexml{%
+ \openmoodleout%
+ }{}%
+}
+\AtEndDocument{
+ \@moodle@ifgeneratexml{%
+ \closemoodleout%
+ }{}%
+}
\def\moodleset#1{\setkeys{moodle}{#1}}%
\def\generate@moodle@write@code{%
\@ifnextchar*\generate@moodle@write@data\generate@moodle@write@html
@@ -174,6 +304,20 @@
}%
}%
+\def\generate@moodle@write@html@noptag#1<#2>#3{%
+\xa\gdef\csname moodle@write#1\endcsname{%
+\xa\def\xa\test@iii\xa{#3}%
+\ifx\test@iii\@moodle@empty
+\writetomoodle[2]{ <#2 format="html"><text/></#2>}%
+\else
+\xa\converttohtmlmacro\xa\moodle@htmltowrite\xa{#3}%
+\writetomoodle[2]{ <#2 format="html">}%
+\writetomoodle[4]{ <text><![CDATA[\moodle@htmltowrite]]></text>}%
+\writetomoodle[2]{ </#2>}%
+\fi
+}%
+}%
+
\def\generate@moodle@write@data*#1<#2>#3{%
% #1 = NAME for \moodle@writeNAME
% #2 = HTML tag
@@ -183,13 +327,24 @@
}%
}%
+\def\generate@moodle@write@tags#1{%
+ % #1 = NAME for \moodle@writeNAME
+ % #3 = what, exactly, to write
+ \xa\gdef\csname moodle@writetags\endcsname{%
+ %\xa\xa\xdef\xa\xa\ds\xa\xa{Encountered '\string #1'}\show\ds
+ \xa\xdef\xa\test@iii\xa{\moodle@tags}%
+ \ifx\test@iii\@moodle@empty\relax\else
+ \xa\converttohtmlmacro\xa\moodle@htmltowrite\xa{\moodle@tags}%
+ \writetomoodle[2]{ <tags>}%
+ \writetomoodle[4]{ <tag><text><![CDATA[\moodle@htmltowrite]]></text></tag>}%
+ \writetomoodle[2]{ </tags>}%
+ \fi
+ }%
+}%
+
%% QUESTIONNAME
\define@cmdkey{moodle}[moodle@]{questionname}{}%
- \gdef\moodle@writequestionname{%
- \writetomoodle[2]{<name>}%
- \writetomoodle[4]{ <text>\moodle@questionname</text>}%
- \writetomoodle[2]{</name>}%
- }%
+\generate@moodle@write@html@noptag{questionname}<name>{\moodle@questionname}%
%% QUESTIONTEXT
%I tried to use questiontext as a key, but it doesn't seem to work.
@@ -205,9 +360,9 @@
\generate@moodle@write@code{questiontext}<questiontext>{\moodle@questiontext}%{%
%% PENALTY FOR WRONG ATTEMPT
- \define@cmdkey{moodle}[moodle@]{penalty}[0.1000000]{}%
+ \define@cmdkey{moodle}[moodle@]{penalty}[0.10]{}%
\generate@moodle@write@code*{penalty}<penalty>{\moodle@penalty}%
- \moodleset{penalty}%
+ \moodleset{penalty=0.10}%
%% FEEDBACK
% Moodle allows for feedback tailored to each question,
@@ -221,7 +376,7 @@
\define@cmdkey{moodle}[moodle@]{feedback}[]{}%
\generate@moodle@write@code{generalfeedback}<generalfeedback>{\moodle@feedback}%
\generate@moodle@write@code{feedback}<feedback>{\moodle@feedback}%
- \moodleset{feedback}%
+ \moodleset{feedback={}}%
%% DEFAULT GRADE
%The next line creates \moodle@defaultgrade,
@@ -247,17 +402,27 @@
\moodle@writehidden%
}%
+%% TAGS
+ %The next line creates \moodle@tags,
+ %which defines a "tag" (i.e., keyword) for the question.
+ %Key calls like [tags={random}] set \moodle@tags.
+ \define@cmdkey{moodle}[moodle@]{tags}[]{}%
+ \generate@moodle@write@tags{\csname moodle@tags\endcsname}%
+ \moodleset{tags}%
%% FRACTION -- how much this answer is worth out of 100 percent
\define@cmdkey{moodle}[moodle@]{fraction}[100]{}%
%We do not create \moodle@writefraction, because the fraction occurs in
%the XML within the answer tag, like <answer fraction="75">.
\moodleset{fraction=100} %This sets the default.
+%% FRACTIONTOL -- the tolerance for fractions with respect to valid values
+ \define@cmdkey{moodle}[moodle@]{fractiontol}[0.1]{}%
+ \moodleset{fractiontol=0.1} %This sets the default.
%% SINGLE and MULTIPLE -- for multichoice, is there 1 right answer or more than 1?
\define@boolkey{moodle}[moodle@]{single}[true]{}%
\generate@moodle@write@code*{single}<single>{\ifmoodle@single true\else false\fi}%
- \moodleset{single}%
+ \moodleset{single=true}%
%The key 'multiple' is an antonym to 'single'.
\define@boolkey{moodle}[moodle@]{multiple}[true]{\ifmoodle@multiple\moodle@singlefalse\else\moodle@singletrue\fi}%
@@ -266,15 +431,15 @@
\generate@moodle@write@code*{shuffle}<shuffleanswers>{\ifmoodle@shuffle 1\else 0\fi}%
\moodleset{shuffle=true}%
-%% TO DO: CORRECTFEEDBACK
-%% TO DO: PARTIALLYCORRECTFEEDBACK
-%% TO DO: INCORRECTFEEDBACK
-%% TO DO: NUMCORRECT key
+%% TODO: CORRECTFEEDBACK
+%% TODO: PARTIALLYCORRECTFEEDBACK
+%% TODO: INCORRECTFEEDBACK
+%% TODO: NUMCORRECT key
%% NUMBERING -- for numbering of multichoice questions
\define@choicekey{moodle}{numbering}%
{alpha,alph,Alpha,Alph,arabic,roman,Roman,%
- abc,ABC,123,iii,IIII,none}[abc]{%
+ abc,ABCD,123,iii,IIII,none}[abc]{%
\def\moodle@numbering{#1}%
\def\test@@i{#1}%
\ifx\test@@i\@moodle@alpha
@@ -282,9 +447,9 @@
\ifx\test@@i\@moodle@alph
\def\moodle@numbering{abc}\fi
\ifx\test@@i\@moodle@Alpha
- \def\moodle@numbering{ABC}\fi
+ \def\moodle@numbering{ABCD}\fi
\ifx\test@@i\@moodle@Alph
- \def\moodle@numbering{ABC}\fi
+ \def\moodle@numbering{ABCD}\fi
\ifx\test@@i\@moodle@arabic
\def\moodle@numbering{123}\fi
\ifx\test@@i\@moodle@roman
@@ -306,7 +471,7 @@
\def\@moodle@roman{roman}%
\def\@moodle@Roman{Roman}%
\def\@moodle@abc{abc}%
- \def\@moodle@ABC{ABC}%
+ \def\@moodle@ABCD{ABCD}%
\def\@moodle@arabicnumbers{123}%
\def\@moodle@iii{iii}%
\def\@moodle@IIII{IIII}%
@@ -315,7 +480,7 @@
\ifx\moodle@numbering\@moodle@abc
\renewcommand\theenumii{\alph{enumii}}%
\fi
- \ifx\moodle@numbering\@moodle@ABC
+ \ifx\moodle@numbering\@moodle@ABCD
\renewcommand\theenumii{\Alph{enumii}}%
\fi
\ifx\moodle@numbering\@moodle@arabicnumbers
@@ -331,7 +496,7 @@
\renewcommand\labelenumii{$\bullet$~}%
\fi
}
- %TO DO: * In the PDF, how should 'none' in a multi look different from
+ %TODO: * In the PDF, how should 'none' in a multi look different from
% short answer or numerical options?
% * Instead of \theenumi and \labelenumi,
% use \@enumdepth to automatically set the correct depth.
@@ -414,7 +579,7 @@
%% RESPONSE REQUIRED
\define@boolkey{moodle}[moodle@]{response required}[true]{}%
- % TO DO: Make synonym 'required'
+ % TODO: Make synonym 'required'
\generate@moodle@write@code*{responserequired}<responserequired>{\csname ifmoodle@response required\endcsname 1\else 0\fi}%
\moodleset{response required=false}%
@@ -444,7 +609,7 @@
%% RESPONSE TEMPLATE
\define@key{moodle}{template}{\long\def\moodle@responsetemplate{#1}}%
- \generate@moodle@write@code{responsetemplate}<responsetemplate>{\moodle@responsetemplate}
+ \generate@moodle@write@html@noptag{responsetemplate}<responsetemplate>{\moodle@responsetemplate}
\moodleset{template={}}%
%% SHOWNUMCORRECT
\define@boolkey{moodle}[moodle@]{shownumcorrect}[true]{}%
@@ -483,53 +648,125 @@
\fi
\xa\xa\xa\def\xa\xa\xa#2\xa\xa\xa{\newxml}%
}%
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% TRUE/FALSE QUESTIONS %%%%%%%%%%%%%%%%%
+%% CALCULATED %%%%%%%%%%%%%%%%%%%%%%%%%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% DESCRIPTION 'QUESTIONS' %%%%%%%%%%%%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% CALCULATED %%%%%%%%%%%%%%%%%%%%%%%%%%
+\def\moodle@makelatextagbox#1{%
+ \Ovalbox{\tiny #1}
+ %\ovalbox{\tiny #1}
+ %\shadowbox{\tiny #1}
+}%
+
+\def\moodle@makelatextag@qtype#1{%
+ \doublebox{\tiny \textsc{#1}}
+}%
+
+\def\moodle@makelatextag@value#1#2{%
+ \moodle@makelatextagbox{\csname moodle@#1\endcsname~#2}
+}%
+\def\moodle@makelatextag@key#1{%
+ \moodle@makelatextagbox{\csname moodle@#1\endcsname}
+}%
+\def\moodle@marks#1{point\ifdim#1pt=1pt \else s\fi}
-\def\moodle@makefrontend#1{%
+\def\moodle@makefrontend#1#2{%
\NewEnviron{#1}[2][]{%
\bgroup
\setkeys{moodle}{##1,questionname={##2}}%
\expandafter\gatheritems\xa{\BODY}%
\let\moodle@questionheader=\gatheredheader
%First, the LaTeX processing
- \item \textbf{\moodle@questionname}\par
+ \item \textbf{\moodle@questionname}
+ \ifmoodle@handout
+ \moodle@makelatextag@qtype{#1}
+ \else
+ \xa\xdef\xa\test@iii\xa{\moodle@tags}%
+ \ifx\test@iii\@moodle@empty\relax\else
+ \hfill tags: \texttt{\moodle@tags}
+ \fi
+ \par
+ \noindent
+ \moodle@makelatextag@qtype{#1}
+ \moodle@makelatextag@value{default grade}{\moodle@marks{\csname moodle@default grade\endcsname}}
+ \moodle@makelatextag@value{penalty}{penalty}
+ \fi
+ #2\par
\noindent
\moodle@questionheader
+ \edef\moodle@generalfeedback{\expandonce\moodle@feedback}
\csname moodle@#1@latexprocessing\endcsname
%Now, writing information to XML
\@moodle@ifgeneratexml{%
\xa\questiontext\xa{\moodle@questionheader}% Save the question text.
+ \csname write#1question\endcsname
\bgroup
\gdef\moodle@answers@xml{}%
\setkeys{moodle}{feedback={}}%
\xa\loopthroughitemswithcommand\xa{\csname save#1answer\endcsname}%
\passvalueaftergroup{\moodle@answers@xml}%
\egroup
- \csname write#1question\endcsname
+ \moodle@writeanswers%
+ \moodle@writetags%
+ \writetomoodle{</question>}%
}{}%
\egroup
}%
}
+\let\description\relax% remove the meaning of existing \description and \enddescription
+\let\enddescription\relax
+\NewEnviron{description}[2][]{%
+ \bgroup
+ \setkeys{moodle}{#1,questionname={#2}}%
+ \let\moodle@questiontext=\BODY
+ \trim@spaces@in\moodle@questiontext
+ \ifx\moodle@questiontext\@empty\relax\else%
+ %First, the LaTeX processing.
+ \item \textbf{\moodle@questionname}
+ \ifmoodle@handout\else
+ \xa\xdef\xa\test@iii\xa{\moodle@tags}%
+ \ifx\test@iii\@moodle@empty\relax\else
+ \hfill tags: \texttt{\moodle@tags}%
+ \fi
+ \par
+ \noindent
+ \fi
+ \moodle@makelatextag@qtype{description}\par
+ \noindent
+ \moodle@questiontext\par
+ \ifmoodle@handout\else
+ \ifx\moodle@feedback\@empty\relax\else
+ \fbox{\parbox{\linewidth}{\emph{\moodle@feedback}}}%
+ \fi
+ \fi
+ %Now, writing information to memory.
+ \@moodle@ifgeneratexml{%
+ \writetomoodle{<question type="description">}%
+ \moodle@writecommondata
+ \moodle@writetags%
+ \writetomoodle{</question>}%
+ }{}%
+ \fi
+ \egroup
+}%
\def\moodle@essay@latexprocessing{%
% Moodle cannot automatically grade an essay,
% but if the user puts \item's in, we can list them in an itemize as notes.
+ \par\noindent \emph{Notes for grader:}
+ \moodle@questionheader
\ifnum\c@numgathereditems>0\relax
- \par\noindent Notes: (not included in XML)
\begin{itemize} \setlength\itemsep{0pt}\setlength\parskip{0pt}%
\loopthroughitemswithcommand{\moodle@print@essay@answer}%
\end{itemize}%
\fi
+ \ifx\moodle@generalfeedback\@empty\relax\else%
+ \fbox{\parbox{\linewidth}{\emph{\moodle@generalfeedback}}}%
+ \fi
}
\NewEnviron{essay}[2][]{%
@@ -538,13 +775,35 @@
\expandafter\gatheritems\expandafter{\BODY}%
\let\moodle@questionheader=\gatheredheader
%First, the LaTeX processing.
- \item \textbf{\moodle@questionname}\par
+ \item \textbf{\moodle@questionname}
+ \ifmoodle@handout
+ \moodle@makelatextag@qtype{essay}
+ \else
+ \xa\xdef\xa\test@iii\xa{\moodle@tags}%
+ \ifx\test@iii\@moodle@empty\relax\else
+ \hfill tags: \texttt{\moodle@tags}
+ \fi
+ \par
+ \noindent
+ \moodle@makelatextag@qtype{essay}
+ \moodle@makelatextag@value{default grade}{\moodle@marks{\csname moodle@default grade\endcsname}}
+ \moodle@makelatextag@value{penalty}{penalty}
+ \moodle@makelatextag@key{responseformat}
+ \fi
+ \par
\noindent
- \moodle@questionheader
- \csname moodle@essay@latexprocessing\endcsname
+ \ifx\moodle@responsetemplate\@empty\relax\else%
+ \par\noindent \emph{Template:}
+ \par\fbox{\parbox{\linewidth}{\moodle@responsetemplate}}\par
+ \fi
+ \edef\moodle@generalfeedback{\expandonce\moodle@feedback}
+ \ifmoodle@handout\else
+ \csname moodle@essay@latexprocessing\endcsname
+ \fi
%Now, writing information to memory.
\@moodle@ifgeneratexml{%
\xa\questiontext\xa{\moodle@questionheader}% Save the question text.
+ \writeessayquestion
\bgroup
\gdef\moodle@answers@xml{}%
%
@@ -564,12 +823,15 @@
%
\passvalueaftergroup{\moodle@answers@xml}%
\egroup
- \writeessayquestion
+ \moodle@writeanswers% The 'answers' XML really contains the grader info.
+ \moodle@writeresponsetemplate%
+ \moodle@writetags%
+ \writetomoodle{</question>}%
}{}%
\egroup
}%
-%%%% TO DO
+%%%% TODO
%%%% To make essay work will be tough.
%%%% Every line from \ifnum\c@numgathereditems=0\relax through its \else and \fi,
%%%% with the exception of
@@ -611,9 +873,6 @@
\moodle@writeresponsefieldlines%
\moodle@writeattachmentsallowed%
\moodle@writeattachmentsrequired%
- \moodle@writeanswers% The 'answers' XML really contains the grader info.
- \moodle@writeresponsetemplate%
- \writetomoodle{</question>}%
}%
\def\moodle@print@essay@answer#1{%
@@ -621,6 +880,7 @@
}%
\def\moodle@savegraderinfo#1{%
+ %\def\ds{#1}\show\ds
\bgroup
\moodle@savegraderinfo@int#1\moodle@answer@rdelim
\passvalueaftergroup{\moodle@answers@xml}%
@@ -631,7 +891,8 @@
\moodle@savegraderinfo@int@int%
}%
\def\moodle@savegraderinfo@int@int#1\moodle@answer@rdelim{%
- \xa\converttohtmlmacro\xa\moodle@answertext@html\xa{#1}%
+ \def\moodle@answertext{#1}
+ \xa\converttohtmlmacro\xa\moodle@answertext@html\xa{\moodle@answertext}%
%\trim@spaces@in\moodle@answertext
\ifnum\c@numgathereditems>1\relax
\addto@xml[6]{\moodle@answers@xml}{<li>\moodle@answertext@html</li>}%
@@ -642,15 +903,32 @@
\def\blank{\rule{1in}{0.5pt}}%
-\moodle@makefrontend{shortanswer}%
+\moodle@makefrontend{shortanswer}{\moodle@makelatextag@shortanswer}%
-\def\moodle@shortanswer@latexprocessing{%
- \begin{itemize} \setlength\itemsep{0pt}\setlength\parskip{0pt}%
- \loopthroughitemswithcommand{\moodle@print@shortanswer@answer}%
- \end{itemize}%
+
+\def\moodle@makelatextag@shortanswer{%
+ \csname ifmoodle@case sensitive\endcsname
+ \moodle@makelatextagbox{Case-Sensitive}\relax
+ \else
+ \moodle@makelatextagbox{Case-Insensitive}\relax
+ \fi
}
+\ifmoodle@handout
+ \let\moodle@shortanswer@latexprocessing\relax
+\else
+ \def\moodle@shortanswer@latexprocessing{%
+ \begin{itemize} \setlength\itemsep{0pt}\setlength\parskip{0pt}%
+ \loopthroughitemswithcommand{\moodle@print@shortanswer@answer}%
+ \end{itemize}%
+ \ifx\moodle@generalfeedback\@empty\relax\else%
+ \fbox{\parbox{\linewidth}{\emph{\moodle@generalfeedback}}}%
+ \fi
+ }
+\fi
+
\def\moodle@print@shortanswer@answer#1{%
+ \let\moodle@feedback=\@empty
\moodle@print@shortanswer@answer@int#1\@rdelim
}%
\newcommand\moodle@print@shortanswer@answer@int[1][]{%
@@ -659,9 +937,13 @@
}%
\def\moodle@print@shortanswer@answer@int@int#1\@rdelim{%
\ifx\moodle@fraction\@hundred
- \item #1\quad$\checkmark$%
+ \item #1$~\checkmark$%
\else
- \item #1\quad (\moodle@fraction\%)%
+ \moodle@checkfraction
+ \item #1$~(\moodle@fraction\%)$%
+ \fi
+ \ifx\moodle@feedback\@empty\relax\else
+ \hfill \emph{$\rightarrow$ \moodle@feedback}
\fi
}%
@@ -677,10 +959,14 @@
}%
\def\saveshortansweranswer@int@int#1\moodle@answer@rdelim{%
\def\moodle@answertext{#1}%
+ \trim@spaces@in\moodle@answertext
+ \moodle@checkfraction
\addto@xml[2]{\moodle@answers@xml}{<answer fraction="\moodle@fraction" format="plain_text">}%
\addto@xml[4]{\moodle@answers@xml}{ <text>\moodle@answertext</text>}%
\ifx\moodle@feedback\@empty\relax\else
- \addto@xml[4]{\moodle@answers@xml}{ <feedback format="html"><text><![CDATA[<p>\moodle@feedback</p>]]></text></feedback>}%
+ \trim@spaces@in\moodle@feedback
+ \xa\converttohtmlmacro\xa\moodle@feedback@html\xa{\moodle@feedback}%
+ \addto@xml[4]{\moodle@answers@xml}{ <feedback format="html"><text><![CDATA[<p>\moodle@feedback@html</p>]]></text></feedback>}%
\fi
\addto@xml[2]{\moodle@answers@xml}{</answer>}%
}%
@@ -689,34 +975,57 @@
\writetomoodle{<question type="shortanswer">}%
\moodle@writecommondata%
\moodle@writeusecase%
- \moodle@writeanswers%
- \writetomoodle{</question>}%
}%
-\moodle@makefrontend{numerical}%
+\moodle@makefrontend{numerical}{\moodle@makelatextag@numerical}%
+
-\def\moodle@numerical@latexprocessing{%
- \begin{itemize} \setlength\itemsep{0pt}\setlength\parskip{0pt}%
- \loopthroughitemswithcommand{\moodle@print@numerical@answer}%
- \end{itemize}%
+\def\moodle@makelatextag@numerical{}
+
+\AtEndPreamble{
+ \@ifpackageloaded{siunitx}{\def\moodle@printnum{\num[omit-uncertainty,copy-decimal-marker]}}{\let\moodle@printnum\trim@spaces}%
}
+\ifmoodle@handout
+ \let\moodle@numerical@latexprocessing\relax
+\else
+ \def\moodle@numerical@latexprocessing{%
+ \begin{itemize} \setlength\itemsep{0pt}\setlength\parskip{0pt}%
+ \loopthroughitemswithcommand{\moodle@print@numerical@answer}%
+ \end{itemize}%
+ \ifx\moodle@generalfeedback\@empty\relax\else%
+ \fbox{\parbox{\linewidth}{\emph{\moodle@generalfeedback}}}%
+ \fi
+ }
+\fi
+
\def\moodle@print@numerical@answer#1{%
- \moodle@print@numerical@answer@int#1\@rdelim
+ \let\moodle@feedback=\@empty
+ \bgroup
+ \moodle@print@numerical@answer@int#1\@rdelim
+ \egroup
}%
\newcommand\moodle@print@numerical@answer@int[1][]{%
\setkeys{moodle}{#1}%
\moodle@print@numerical@answer@int@int%
}%
\def\moodle@print@numerical@answer@int@int#1\@rdelim{%
- \ifdim0pt=\moodle@tolerance pt\relax
- \def\moodle@numericalprint@tolerance{}%
+ \xdef\test@i{\trim@spaces{#1}}%
+ \ifx\test@i\@star
+ \item \test@i
\else
- \edef\moodle@numericalprint@tolerance{\noexpand\pm\moodle@tolerance}%
+ \item \moodle@printnum{#1}%
+ \ifnum\z@=\moodle@tolerance\else
+ $\,\pm\,$\moodle@printnum{\moodle@tolerance}%
+ \fi
\fi
\ifx\moodle@fraction\@hundred
- \item $#1\moodle@numericalprint@tolerance\quad\checkmark$%
+ $~\checkmark$%
\else
- \item $#1\moodle@numericalprint@tolerance$\quad (\moodle@fraction\%)%
+ \moodle@checkfraction
+ $~(\moodle@fraction\%)$%
+ \fi
+ \ifx\moodle@feedback\@empty\relax\else
+ \hfill \emph{$\rightarrow$ \moodle@feedback}%
\fi
}%
@@ -732,11 +1041,17 @@
}%
\def\savenumericalanswer@int@int#1\moodle@answer@rdelim{%
\def\moodle@answertext{#1}%
+ \trim@spaces@in\moodle@answertext
+ \moodle@checkfraction
\addto@xml[2]{\moodle@answers@xml}{<answer fraction="\moodle@fraction" format="plain_text">}%
\addto@xml[4]{\moodle@answers@xml}{ <text>\moodle@answertext</text>}%
- \addto@xml[4]{\moodle@answers@xml}{ <tolerance>\moodle@tolerance</tolerance>}%
+ \ifx\moodle@answertext\@star\else
+ \addto@xml[4]{\moodle@answers@xml}{ <tolerance>\moodle@tolerance</tolerance>}%
+ \fi
\ifx\moodle@feedback\@empty\relax\else
- \addto@xml[4]{\moodle@answers@xml}{ <feedback format="html"><text><![CDATA[<p>\moodle@feedback</p>]]></text></feedback>}%
+ \trim@spaces@in\moodle@feedback
+ \xa\converttohtmlmacro\xa\moodle@feedback@html\xa{\moodle@feedback}%
+ \addto@xml[4]{\moodle@answers@xml}{ <feedback format="html"><text><![CDATA[<p>\moodle@feedback@html</p>]]></text></feedback>}%
\fi
\addto@xml[2]{\moodle@answers@xml}{</answer>}%
}%
@@ -744,59 +1059,155 @@
\gdef\writenumericalquestion{%
\writetomoodle{<question type="numerical">}%
\moodle@writecommondata%
- \moodle@writeanswers%
- \writetomoodle{</question>}%
}%
-\moodle@makefrontend{multi}
+\moodle@makefrontend{multi}{\moodle@makelatextag@multi}%
+
+
+\def\moodle@makelatextag@multi{%
+ \ifmoodle@multiple
+ \moodle@makelatextagbox{Multiple}\relax%
+ \else
+ \moodle@makelatextagbox{Single}\relax%
+ \fi
+ \ifmoodle@handout\else
+ \ifmoodle@shuffle
+ \moodle@makelatextagbox{Shuffle}\relax%
+ \fi
+ \fi
+}
\def\moodle@multi@latexprocessing{%
- \moodle@countcorrectanswers
- \begin{enumerate}\moodle@obeynumberingstyle
- %\renewcommand{\theenumi}{\alph{enumi}}%
- \setlength\itemsep{0pt}\setlength\parskip{0pt}%
- \loopthroughitemswithcommand{\moodle@print@multichoice@answer}%
- \end{enumerate}%
+ \moodle@countcorrectanswers%
+ \ifmoodle@handout\NewList{answerlist}\fi
+ \begin{enumerate}\moodle@obeynumberingstyle%
+ %\renewcommand{\theenumi}{\alph{enumi}}%
+ \setlength\itemsep{0pt}\setlength\parskip{0pt}%
+ \loopthroughitemswithcommand{\moodle@print@multichoice@answer}%
+ \ifmoodle@handout
+ \ifmoodle@shuffle
+ \let\moodle@multi@loop=\ForEachRandomItem
+ \else
+ \let\moodle@multi@loop=\ForEachFirstItem
+ \fi
+ \moodle@multi@loop{answerlist}{Answer}{\Answer}%
+ \fi
+ \end{enumerate}%
+ \ifmoodle@handout\else
+ \ifx\moodle@generalfeedback\@empty\relax\else%
+ \fbox{\parbox{\linewidth}{\emph{\moodle@generalfeedback}}}%
+ \fi
+ \fi
}
\def\moodle@print@multichoice@answer#1{%
- \moodle@print@multichoice@answer@int#1\@rdelim
+ \let\moodle@feedback=\@empty%
+ \moodle@print@multichoice@answer@int#1 \@rdelim%
}%
\newcommand\moodle@print@multichoice@answer@int[1][]{%
- \setkeys{moodle}{fraction=0,#1}%
- \moodle@print@multichoice@answer@int@int
+ \let\moodle@fraction\@empty%
+ \setkeys{moodle}{#1}%
+ \moodle@print@multichoice@answer@int@int%
}%
\def\moodle@print@multichoice@answer@int@int#1#2\@rdelim{%
\def\test@i{#1}%
- \ifmoodle@single
- \ifx\test@i\@star
- \item #2$~\checkmark$%
+ \def\test@ii{#2}%
+ \def\moodle@answertext{\item }%
+ \ifx\test@i\@star%
+ \g@addto@macro\moodle@answertext{#2}%
+ \ifmoodle@single%
+ \setkeys{moodle}{fraction=100}%
\else
- \item #1#2%
+ \setkeys{moodle}{fraction=\moodle@autopoints}%
\fi
\else
- \ifx\test@i\@star
- \item #2%
- \setkeys{moodle}{fraction=\moodle@autopoints}%
- \else
- \item #1#2%
+ \g@addto@macro\moodle@answertext{#1#2}%
+ \fi
+ \trim@spaces@in\moodle@answertext%
+ \trim@spaces@in\moodle@answertext%
+ \ifmoodle@handout\else
+ \ifmoodle@single%
+ \ifx\moodle@fraction\@empty\relax%
+ \setkeys{moodle}{fraction=0}%
+ \fi
+ \ifx\moodle@fraction\@hundred%
+ \trim@spaces@in\moodle@answertext%
+ \g@addto@macro\moodle@answertext{$~\checkmark$}%
+ \else
+ \moodle@checkfraction
+ \ifdim0pt=\moodle@fraction pt\relax\else%
+ \g@addto@macro\moodle@answertext{$~(\moodle@fraction\%)$}%
+ \fi
+ \fi
+ \else% multiple
+ \ifx\moodle@fraction\@empty\relax%
+ \setkeys{moodle}{fraction=\moodle@autosanctions}%
+ \fi
+ \moodle@checkfraction
+ \g@addto@macro\moodle@answertext{$~(\moodle@fraction\%)$}%
\fi
- $~(\moodle@fraction\%)$
+ \fi
+ \ifmoodle@handout
+ \def\temp{\InsertLastItem{answerlist}}%
+ \xa\temp\xa{\moodle@answertext}%
+ \else
+ \ifx\moodle@feedback\@empty\relax\else%
+ \g@addto@macro\moodle@answertext{\hfill \emph{$\rightarrow$ \moodle@feedback}}%
+ \fi
+ \moodle@answertext
\fi
}%
- \newcounter{moodle@numcorrectanswers}%
+ \newcounter{moodle@numcorrectanswers}% count the stars
+ \newcounter{moodle@numincorrectanswers}% count the items without fraction key indicated
\newlength{\moodle@pointspercorrect}%
+ \newlength{\moodle@pointsperincorrect}%
+ \newlength{\moodle@sumofpositivefractions}% sums user-set positive fractions
+ \newlength{\moodle@sumofnegativefractions}% sums user-set negative fractions
\def\moodle@countcorrectanswers{%
\setcounter{moodle@numcorrectanswers}{0}%
+ \setcounter{moodle@numincorrectanswers}{0}%
\global\setlength{\moodle@pointspercorrect}{100pt}%
+ \global\setlength{\moodle@pointsperincorrect}{-100pt}%
+ \global\setlength{\moodle@sumofpositivefractions}{0pt}%
+ \global\setlength{\moodle@sumofnegativefractions}{0pt}%
\loopthroughitemswithcommand{\moodle@countcorrectanswers@a}%
- \ifnum0=\c@moodle@numcorrectanswers\relax
- \PackageError{moodle}{No correct answers given for multiple choice question.}{Please mark at least one answer correct.}%
- \gdef\moodle@autopoints{0}%
+ \global\advance\moodle@pointspercorrect by-\moodle@sumofpositivefractions\relax%
+ \def\ds{\strip@pt\moodle@sumofpositivefractions}%
+ \ifnum0=\c@moodle@numcorrectanswers\relax%
+ % autopoints will never be used but we check if the sum of positive fractions is 100%
+ \ifdim\moodle@pointspercorrect<-\moodle@fractiontol pt\relax%
+ \PackageWarning{moodle}{Positive fractions sum up to more than 100 (here: \ds)}%
+ \else
+ \ifdim\moodle@pointspercorrect>\moodle@fractiontol pt\relax%
+ \PackageError{moodle}{Positive fractions sum up to less than 100 (here: \ds)}%
+ \fi
+ \fi
+ \else
+ \ifdim0pt<\moodle@pointspercorrect\relax\else%
+ % we have starred items so the sum of user-set positive fractions must be less than 100%
+ % otherwise, starred items would lead to penalties
+ \PackageError{moodle}{Positive fractions sum up to 100 or more (here: \ds):
+ there is no positive points left to be given to starred items.}%
+ \fi
+ \global\divide\moodle@pointspercorrect by \c@moodle@numcorrectanswers\relax%
+ \fi
+ \gdef\moodle@autopoints{\strip@pt\moodle@pointspercorrect}%
+ \global\advance\moodle@pointsperincorrect by-\moodle@sumofnegativefractions\relax%
+ \def\ds{\strip@pt\moodle@sumofnegativefractions}%
+ \ifnum0=\c@moodle@numincorrectanswers\relax%
+ % autosanctions will never be used and
+ % we do not care about the sum of negative fractions (might be less than -100)
\else
- \global\divide\moodle@pointspercorrect by \c@moodle@numcorrectanswers\relax
- \edef\moodle@autopoints{\strip@pt\moodle@pointspercorrect}%
+ \ifdim0pt<\moodle@pointsperincorrect\relax%
+ % we have items without fractions set: to prevent auto sanctions from becoming bonuses,
+ % such items are neutralized.
+ \PackageWarning{moodle}{Negative fractions sum up to -100 or less (here: \ds):
+ items with no fraction key set will be considered as neutral.}%
+ \global\setlength{\moodle@pointsperincorrect}{0pt}%
+ \fi
+ \global\divide\moodle@pointsperincorrect by \c@moodle@numincorrectanswers\relax%
\fi
+ \gdef\moodle@autosanctions{\strip@pt\moodle@pointsperincorrect}%
}
\def\moodle@countcorrectanswers@a#1{%
%The grouping is to keep key answer-specific key changes local.
@@ -805,30 +1216,77 @@
\egroup
}%
\newcommand\moodle@countcorrectanswers@b[1][]{%
- \setkeys{moodle}{fraction=0,#1}%
- \moodle@countcorrectanswers@c%
+ %\ifx&#1&%
+ \let\moodle@fraction\@empty%
+ \setkeys{moodle}{#1}%
+ \moodle@countcorrectanswers@c%
+ %\fi
}%
\def\moodle@countcorrectanswers@c#1#2\moodle@answer@rdelim{%
\def\test@i{#1}%
\ifx\test@i\@star
\stepcounter{moodle@numcorrectanswers}%
\else
- \global\addtolength{\moodle@pointspercorrect}{-\moodle@fraction pt}%
+ \ifx\moodle@fraction\@empty\relax%
+ \stepcounter{moodle@numincorrectanswers}%
+ \else
+ \ifdim0pt<\moodle@fraction pt\relax%
+ \global\addtolength{\moodle@sumofpositivefractions}{\moodle@fraction pt}%
+ \else
+ \global\addtolength{\moodle@sumofnegativefractions}{\moodle@fraction pt}%
+ \fi
+ \fi
\fi
}%
- \def\moodle@setautopoints#1pt{%
- \gdef\moodle@autopoints{#1}%
+ \newlength{\test@fraction}%
+ \newlength{\test@lower}%
+ \newlength{\test@upper}%
+ \def\moodle@fractionerror{%
+ \def\ds{\moodle@fraction}%
+ \PackageError{moodle}{the current fraction is not a valid value (here: \ds)}%
+ }
+ {\catcode`|=3\relax
+ \gdef\moodle@validfractionlist{0|5|10|11.11111|12.5|14.28571|16.66667|20|25|30|33.33333|40|50|60|66.66667|70|75|80|83.33333|90|100}}%
+ \def\moodle@isfractionnear#1{%
+ \setlength{\test@lower}{#1 pt}%
+ \addtolength{\test@lower}{-\moodle@fractiontol pt}%
+ \setlength{\test@upper}{#1 pt}%
+ \addtolength{\test@upper}{\moodle@fractiontol pt}%
+ \ifdim\test@upper>\test@fraction\relax
+ \ifdim\test@lower<\test@fraction\relax
+ \gdef\test@fractionmatched{#1}%
+ \fi
+ \fi
+ }
+ \def\moodle@checkfraction{%
+ %\def\test@i{#1}%
+ \setlength{\test@fraction}{\moodle@fraction pt}%
+ % take the absolute value
+ \ifdim0pt>\test@fraction\relax%
+ \setlength{\test@fraction}{-\moodle@fraction pt}%
+ \fi
+ % test if the fraction is an admissible value
+ \let\test@fractionmatched\@empty
+ \forlistloop{\moodle@isfractionnear}{\moodle@validfractionlist}%
+ \ifx\test@fractionmatched\@empty\relax
+ \moodle@fractionerror%
+ \fi
+ \ifdim\moodle@fraction pt<-\moodle@fractiontol pt\relax%
+ \setkeys{moodle}{fraction=-\test@fractionmatched}%
+ \else
+ \setkeys{moodle}{fraction=\test@fractionmatched}%
+ \fi
}
-
\def\savemultianswer#1{%
\bgroup
- \savemultianswer@int#1\moodle@answer@rdelim
+ \savemultianswer@int#1 \moodle@answer@rdelim
\passvalueaftergroup{\moodle@answers@xml}%
\egroup
}%
\newcommand\savemultianswer@int[1][]{%
- \setkeys{moodle}{fraction=0,#1}%
+ \let\moodle@fraction\@empty%
+ \setkeys{moodle}{#1}%
\savemultianswer@int@int%
}%
\def\savemultianswer@int@int#1#2\moodle@answer@rdelim{%
@@ -843,12 +1301,23 @@
\else
\def\moodle@answertext{#1#2}%
\fi
+ \ifx\moodle@fraction\@empty\relax%
+ \ifmoodle@single\relax
+ \setkeys{moodle}{fraction=0}%
+ \else% multiple
+ \setkeys{moodle}{fraction=\moodle@autosanctions}%
+ \fi
+ \fi
+ \trim@spaces@in\moodle@answertext
\trim@spaces@in\moodle@answertext
+ \moodle@checkfraction
\addto@xml[2]{\moodle@answers@xml}{<answer fraction="\moodle@fraction" format="html">}%
\xa\converttohtmlmacro\xa\moodle@answertext@html\xa{\moodle@answertext}%
\addto@xml[4]{\moodle@answers@xml}{ <text><![CDATA[<p>\moodle@answertext@html</p>]]></text>}%
\ifx\moodle@feedback\@empty\relax\else
- \addto@xml[4]{\moodle@answers@xml}{ <feedback format="html"><text><![CDATA[<p>\moodle@feedback</p>]]></text></feedback>}%
+ \trim@spaces@in\moodle@feedback
+ \xa\converttohtmlmacro\xa\moodle@feedback@html\xa{\moodle@feedback}%
+ \addto@xml[4]{\moodle@answers@xml}{ <feedback format="html"><text><![CDATA[<p>\moodle@feedback@html</p>]]></text></feedback>}%
\fi
\addto@xml[2]{\moodle@answers@xml}{</answer>}%
}%
@@ -859,42 +1328,322 @@
\moodle@writesingle%
\moodle@writeshuffle%
\moodle@writeanswernumbering%
- \moodle@writeanswers%
- \writetomoodle{</question>}%
}%
-\let\answer=\hfill
-\moodle@makefrontend{matching}
-\def\moodle@matching@latexprocessing{%
+\NewEnviron{truefalse}[2][]{%
+ \bgroup
+ \setkeys{moodle}{#1,questionname={#2}}%
+ \expandafter\gatheritems\xa{\BODY}%
+ \let\moodle@questionheader=\gatheredheader
+ %First, the LaTeX processing
+ \item \textbf{\moodle@questionname}
+ \ifmoodle@handout
+ \moodle@makelatextag@qtype{truefalse}
+ \else
+ \xa\xdef\xa\test@iii\xa{\moodle@tags}%
+ \ifx\test@iii\@moodle@empty\relax\else
+ \hfill tags: \texttt{\moodle@tags}
+ \fi
+ \par
+ \noindent
+ \moodle@makelatextag@qtype{truefalse}
+ \moodle@makelatextag@value{default grade}{\moodle@marks{\csname moodle@default grade\endcsname}}
+ \fi
+ \par
+ \noindent
+ \moodle@questionheader
+ \edef\moodle@generalfeedback{\expandonce\moodle@feedback}
+ \moodle@truefalse@latexprocessing
+ %Now, writing information to XML
+ \@moodle@ifgeneratexml{%
+ \setkeys{moodle}{penalty=1}%
+ \xa\questiontext\xa{\moodle@questionheader}% Save the question text.
+ \csname writetruefalsequestion\endcsname
+ \bgroup
+ \gdef\moodle@answers@xml{}%
+ \setkeys{moodle}{feedback={}}%
+ \xa\loopthroughitemswithcommand\xa{\xa\savetruefalseanswer}%
+ \ifnum\c@numgathereditems=1\relax%
+ \setcounter{currentitemnumber}{2}%
+ \savetruefalseanswer{}
+ \fi
+ \passvalueaftergroup{\moodle@answers@xml}%
+ \egroup
+ \moodle@writeanswers%
+ \moodle@writetags%
+ \writetomoodle{</question>}%
+ }{}%
+ \egroup
+ }%
+
+
+\def\moodle@truefalse@latexprocessing{%
+ \setcounter{moodle@numcorrectanswers}{0}%
+ \begin{itemize} \setlength\itemsep{0pt}\setlength\parskip{0pt}%
+ \loopthroughitemswithcommand{\moodle@print@truefalse@answer}%
+ \ifnum\c@currentitemnumber=2%
+ \item \textbf{False}%
+ \fi
+ \end{itemize}
+ \ifmoodle@handout\else
+ \ifx\moodle@generalfeedback\@empty\relax\else%
+ \fbox{\parbox{\linewidth}{\emph{\moodle@generalfeedback}}}%
+ \fi
+ \fi
+ \ifnum\c@moodle@numcorrectanswers=0\relax%
+ \PackageError{moodle}{No answer is explicitly marked as correct (*). Be sure one answer leads to points.}%
+ \fi
+ \ifnum\c@moodle@numcorrectanswers>1\relax%
+ \PackageError{moodle}{Two answers are explicitly marked as correct (*). Be sure only one answer leads to points.}%
+ \fi
+}
+
+ \def\moodle@print@truefalse@answer#1{% here # is all what comes after "\item", that is "[options]* text"
+ \let\moodle@feedback=\@empty
+ \moodle@print@truefalse@answer@int#1\@rdelim % add an end delimiter:
+ }%
+ \newcommand\moodle@print@truefalse@answer@int[1][]{% with the optional argument, catch options and set them as keys
+ \setkeys{moodle}{#1}%
+ \moodle@print@truefalse@answer@int@int% applies to the rest: "* text\@rdelim"
+ }%
+ \def\moodle@print@truefalse@answer@int@int#1\@rdelim{% this is just to treat appart the case where nothing follows
+ \def\test@i{#1}
+ \trim@spaces@in\test@i
+ \ifx\test@i\@empty\relax
+ \moodle@print@truefalse@answer@int@int@empty
+ \else
+ \moodle@print@truefalse@answer@int@int@int#1\@rdelim
+ \fi
+ }%
+ \def\moodle@print@truefalse@answer@int@int@empty{%
+ \ifnum\c@currentitemnumber=1%
+\def\moodle@answertext{True}%
+ \fi
+ \ifnum\c@currentitemnumber=2%
+\def\moodle@answertext{False}%
+ \fi
+ \item \textbf{\moodle@answertext}%
+ \ifmoodle@handout\else
+ \ifx\moodle@feedback\@empty\relax\else
+ ~\hfill \emph{$\rightarrow$ \moodle@feedback}%
+ \fi
+ \fi
+ }%
+ \def\moodle@print@truefalse@answer@int@int@int#1#2\@rdelim{%
+ \ifnum\c@currentitemnumber=1%
+\def\moodle@answertext{True}%
+ \fi
+ \ifnum\c@currentitemnumber=2%
+\def\moodle@answertext{False}%
+ \fi
+ \item \textbf{\moodle@answertext}%
+ \ifnum\c@currentitemnumber<3%
+ \def\test@i{#1}%
+ %\trim@spaces@in\test@i
+ \ifx\test@i\@star
+ \ifmoodle@handout\else
+ ~$\checkmark$%
+ \fi
+ \stepcounter{moodle@numcorrectanswers}%
+ \else
+ ~%
+ \fi
+ \ifmoodle@handout\else
+ \ifx\moodle@feedback\@empty\relax
+ \def\test@ii{#2}%
+ \trim@spaces@in\test@ii
+ \ifx\test@ii\@empty\relax\else
+ \ifx\test@i\@star%
+ \hfill \emph{$\rightarrow$ #2}%
+ \else%
+ \hfill \emph{$\rightarrow$ #1#2}%
+ \fi
+ \fi
+ \else
+ \hfill \emph{$\rightarrow$ \moodle@feedback}%
+ \fi
+ \fi
+ \fi
+ }%
+
+\def\savetruefalseanswer#1{%
\bgroup
- \let\answer=\hfill
- \begin{enumerate}\renewcommand{\theenumi}{\alph{enumi}}\setlength\itemsep{0pt}\setlength\parskip{0pt}%
- \loopthroughitemswithcommand{\moodle@print@matching@answer}%
- \end{enumerate}%
+ \savetruefalseanswer@int#1\moodle@answer@rdelim
+ \passvalueaftergroup{\moodle@answers@xml}%
\egroup
-}
- \long\def\moodle@print@matching@answer#1{%
- \moodle@print@matching@answer@int#1\@rdelim
+}%
+ \newcommand\savetruefalseanswer@int[1][]{%
+ \setkeys{moodle}{#1}%
+ \savetruefalseanswer@int@int%
}%
- \newcommand\moodle@print@matching@answer@int[1][]{%
- \moodle@print@matching@answer@int@int\relax
+ \def\savetruefalseanswer@int@int#1\moodle@answer@rdelim{%
+ \def\test@i{#1}
+ \trim@spaces@in\test@i
+ \ifx\test@i\@empty\relax
+ \savetruefalseanswer@int@int@empty
+ \else
+ \savetruefalseanswer@int@int@int#1\moodle@answer@rdelim
+ \fi
}%
- \long\def\moodle@print@matching@answer@int@int#1\answer#2\@rdelim{%
- \item #1\hfill #2%
+ \def\savetruefalseanswer@int@int@empty{%
+ \setkeys{moodle}{fraction=0}%
+ \ifnum\c@currentitemnumber=1%
+\def\moodle@answertext{true}%
+ \fi
+ \ifnum\c@currentitemnumber=2%
+\def\moodle@answertext{false}%
+ \fi
+ \ifnum\c@currentitemnumber<3%
+ \addto@xml[2]{\moodle@answers@xml}{<answer fraction="\moodle@fraction" format="plain_text">}%
+ \addto@xml[4]{\moodle@answers@xml}{ <text>\moodle@answertext</text>}%
+ \ifx\moodle@feedback\@empty\relax\else
+ \trim@spaces@in\moodle@feedback
+ \xa\converttohtmlmacro\xa\moodle@feedback@html\xa{\moodle@feedback}%
+ \addto@xml[4]{\moodle@answers@xml}{ <feedback format="html"><text><![CDATA[<p>\moodle@feedback@html</p>]]></text></feedback>}%
+ \fi
+ \addto@xml[2]{\moodle@answers@xml}{</answer>}%
+ \fi
+ }%
+ \def\savetruefalseanswer@int@int@int#1#2\moodle@answer@rdelim{%
+ \def\test@i{#1}%
+ \ifx\test@i\@star
+ \setkeys{moodle}{fraction=100}%
+ \else
+ \setkeys{moodle}{fraction=0}%
+ \fi
+ \ifnum\c@currentitemnumber=1%
+\def\moodle@answertext{true}%
+ \fi
+ \ifnum\c@currentitemnumber=2%
+\def\moodle@answertext{false}%
+ \fi
+ \ifnum\c@currentitemnumber<3%
+ \addto@xml[2]{\moodle@answers@xml}{<answer fraction="\moodle@fraction" format="plain_text">}%
+ \addto@xml[4]{\moodle@answers@xml}{ <text>\moodle@answertext</text>}%
+ \ifx\moodle@feedback\@empty\relax
+ \def\test@ii{#2}
+ \ifx\test@ii\@empty\relax\else
+ \ifx\test@i\@star
+ \xa\converttohtmlmacro\xa\moodle@feedback@html\xa{#2}%
+ \else%
+ \xa\converttohtmlmacro\xa\moodle@feedback@html\xa{#1#2}%
+ \fi%
+ \addto@xml[4]{\moodle@answers@xml}{ <feedback format="html"><text><![CDATA[<p>\moodle@feedback@html</p>]]></text></feedback>}%
+ \fi
+ \else
+ \trim@spaces@in\moodle@feedback
+ \xa\converttohtmlmacro\xa\moodle@feedback@html\xa{\moodle@feedback}%
+ \addto@xml[4]{\moodle@answers@xml}{ <feedback format="html"><text><![CDATA[<p>\moodle@feedback@html</p>]]></text></feedback>}%
+ \fi
+ \addto@xml[2]{\moodle@answers@xml}{</answer>}%
+ \fi
}%
+\gdef\writetruefalsequestion{%
+ \writetomoodle{<question type="truefalse">}%
+ \moodle@writecommondata%
+}%
+
+\moodle@makefrontend{matching}{\moodle@makelatextag@matching}%
+
+
+\def\moodle@makelatextag@matching{%
+ \ifmoodle@handout\else
+ \ifmoodle@draganddrop
+ \moodle@makelatextagbox{Drag and drop}\relax%
+ \fi
+ \ifmoodle@shuffle
+ \moodle@makelatextagbox{Shuffle}\relax%
+ \fi
+ \fi
+}
+
+\def\moodle@matching@latexprocessing{%
+ \bgroup
+ %\let\answer=\hfill
+ \par%\noindent
+ \ifmoodle@handout
+ \NewList{questionlist}
+ \NewList{answerlist}
+ \fi
+ \def\matching@table@text{}%
+ % \ifnum\c@numgathereditems>2\relax%
+ \setcounter{moodle@numcorrectanswers}{0}% Here this counter is for "questions" (items on the left column)
+ \loopthroughitemswithcommand{\moodle@print@matching@answer}%
+ \ifnum\c@numgathereditems<3%
+ \PackageWarning{moodle}{Moodle expects at least three "answers" with matching type}
+ \fi
+ \ifnum\c@moodle@numcorrectanswers<2%
+ \PackageWarning{moodle}{Moodle expects at least two "questions" with the matching type}
+ \fi
+ \ifmoodle@handout
+ \ifmoodle@shuffle
+ \let\moodle@matching@loop=\ForEachRandomItem
+ \else
+ \let\moodle@matching@loop=\ForEachFirstItem
+ \fi
+ \moodle@matching@loop{questionlist}{Question}{
+ \xdef\test@i{\Question}%
+ \ExtractRandomItem{answerlist}{Answer}%
+ \ifx\test@i\@empty
+ \xdef\matching@table@text{\expandonce\matching@table@text & & $\bullet$~\expandonce\Answer\\}%
+ \else
+ \xdef\matching@table@text{\expandonce\matching@table@text\expandonce\Question~$\bullet$ & & $\bullet$~\expandonce\Answer\\}%
+ \fi
+ }%
+ \fi
+ \begin{tabular}{@{}>{\raggedleft}p{.45\linewidth}p{.1\linewidth}p{.45\linewidth}@{}}%
+ \matching@table@text
+ \end{tabular}%
+ \par
+ \ifmoodle@handout\else
+ \ifx\moodle@generalfeedback\@empty\relax\else%
+ \fbox{\parbox{\linewidth}{\emph{\moodle@generalfeedback}}}%
+ \fi
+ \fi
+ \egroup
+}
+
+\long\def\moodle@print@matching@answer#1{%
+ \moodle@print@matching@answer@int#1 \@rdelim
+}%
+\newcommand\moodle@print@matching@answer@int[1][]{%
+ \moodle@print@matching@answer@int@int
+}%
+\long\def\moodle@print@matching@answer@int@int#1\answer#2\@rdelim{%
+ %\typeout{\string#1 \answer \string#2}%
+ \def\test@i{#1}%
+ \trim@spaces@in\test@i
+ \ifmoodle@handout
+ \ifx\test@i\@empty
+ \InsertLastItem{questionlist}{\@empty}%
+ \else
+ \InsertLastItem{questionlist}{#1}%
+ \fi
+ \InsertLastItem{answerlist}{#2}%
+ \else
+ \ifx\test@i\@empty
+ \g@addto@macro\matching@table@text{&&$\bullet$~#2\\}%
+ \else
+ \stepcounter{moodle@numcorrectanswers}%
+ \xa\g@addto@macro\xa\matching@table@text\xa{\test@i~$\bullet$&\leavevmode\cleaders\hb@xt@.44em{\hss$\cdot$\hss}\hfill\kern\z@&$\bullet$~#2\\}%
+ \fi
+ \fi
+}%
+
\long\def\savematchinganswer#1{%
\bgroup
- \savematchinganswer@int#1\moodle@answer@rdelim%
+ \savematchinganswer@int#1 \moodle@answer@rdelim%
\passvalueaftergroup{\moodle@answers@xml}%
\egroup
}%
\newcommand\savematchinganswer@int[1][]{%
\setkeys{moodle}{#1}%
- \xa\savematchinganswer@int@int\space%
+ \savematchinganswer@int@int%\space
}%
\long\def\savematchinganswer@int@int#1\answer#2\moodle@answer@rdelim{%
+ %\typeout{\string#1 \answer \string#2}%
% Note that #1 may simply be \relax.
\def\moodle@subquestiontext{#1}%
\def\moodle@subanswertext{#2}%
@@ -915,9 +1664,6 @@
\else
\addto@xml[4]{\moodle@answers@xml}{ <answer><text>\moodle@subanswertext</text></answer>}%
\fi
- \ifx\moodle@feedback\@empty\relax\else
- \addto@xml[4]{\moodle@answers@xml}{ <feedback format="html"><text><![CDATA[<p>\moodle@feedback</p>]]></text></feedback>}%
- \fi
\addto@xml[2]{\moodle@answers@xml}{</subquestion>}%
}%
@@ -928,13 +1674,11 @@
\writetomoodle{<question type="matching">}%
\fi
\moodle@writecommondata%
- \moodle@writesingle%
\moodle@writeshuffle%
- \moodle@writeanswernumbering%
- \moodle@writeanswers%
- \writetomoodle{</question>}%
}%
+\newif\ifmoodle@clozemode
+\moodle@clozemodefalse
\NewEnviron{cloze}[2][]{%
\bgroup
\setkeys{moodle}{default grade=1}%
@@ -942,9 +1686,30 @@
% A cloze question won't have any \item's in it, so we just use \BODY.
\moodle@enableclozeenvironments
%First, the LaTeX processing.
- \item \textbf{\moodle@questionname}\par
+ \item \textbf{\moodle@questionname}
+ \ifmoodle@handout
+ \moodle@makelatextag@qtype{cloze}
+ \else
+ \xa\xdef\xa\test@iii\xa{\moodle@tags}%
+ \ifx\test@iii\@moodle@empty\relax\else
+ \hfill tags: \texttt{\moodle@tags}
+ \fi
+ \par
+ \noindent
+ \moodle@makelatextag@qtype{cloze}
+ \moodle@makelatextag@value{default grade}{\moodle@marks{\csname moodle@default grade\endcsname}}
+ \moodle@makelatextag@value{penalty}{penalty}
+ \fi
+ \par
\noindent
\BODY
+ \edef\moodle@generalfeedback{\expandonce\moodle@feedback}
+ %\csname moodle@cloze@latexprocessing\endcsname
+ \ifmoodle@handout\else
+ \ifx\moodle@generalfeedback\@empty\relax\else%
+ \fbox{\parbox{\linewidth}{\emph{\moodle@generalfeedback}}}%
+ \fi
+ \fi
%Now, writing information to memory.
\@moodle@ifgeneratexml{%
\xa\questiontext\xa{\BODY}% Save the question text as HTML.
@@ -965,6 +1730,7 @@
\gdef\writeclozequestion{%
\writetomoodle{<question type="cloze">}%
\moodle@writecommondata%
+ \moodle@writetags%
\writetomoodle{</question>}%
}%
@@ -979,40 +1745,87 @@
\def\moodle@clozemulti@output{}%
\xa\g@addto@macro\xa\moodle@clozemulti@output\xa{\moodle@questionheader}%
\def\clozemulti@coding{}%
- \edef\clozemulti@coding{\otherlbrace\csname moodle@default grade\endcsname:}%
+ \edef\clozemulti@coding{\csname moodle@default grade\endcsname:}%
+ \ifmoodle@multiple
+ \PackageWarning{moodle}{Cloze Multiresponse only supported by Moodle 3.5+}
+ \g@addto@macro{\clozemulti@coding}{MULTIRESPONSE}%
+ \else
+ \g@addto@macro{\clozemulti@coding}{MULTICHOICE}%
+ \fi
\ifcase\moodle@multi@mode\relax
- % Case 0: dropdown box style
- \g@addto@macro{\clozemulti@coding}{MULTICHOICE:}%
+ % Case 0: dropdown box style
+ \ifmoodle@shuffle
+ \g@addto@macro{\clozemulti@coding}{_}%
+ \fi
\or
% Case 1: vertical style
- \g@addto@macro{\clozemulti@coding}{MULTICHOICE_V:}%
+ \ifmoodle@multiple
+ \PackageError{moodle}{Vertical mode (dropdown box) incompatible with multiresponse.}
+ \else
+ \g@addto@macro{\clozemulti@coding}{_V}%
+ \fi
\else
% Case 2: horizontal radio buttons
- \g@addto@macro{\clozemulti@coding}{MULTICHOICE_H:}%
+ \g@addto@macro{\clozemulti@coding}{_H}%
+ \fi
+ \ifmoodle@shuffle
+ \PackageWarning{moodle}{Cloze Multi Shuffling only supported by Moodle 3.0+}
+ \g@addto@macro{\clozemulti@coding}{S:}%
+ \else
+ \g@addto@macro{\clozemulti@coding}{:}%
\fi
\bgroup
\setkeys{moodle}{feedback={}}%
\loopthroughitemswithcommand{\saveclozemultichoiceanswer}%
\egroup
- \xa\g@addto@macro\xa\clozemulti@coding\xa{\otherrbrace}%
- \xa\g@addto@macro\xa\moodle@clozemulti@output\xa{\clozemulti@coding}%
+ %\xa\g@addto@macro\xa\clozemulti@coding\xa{\clozerbrace}%
+ \xa\g@addto@macro\xa\moodle@clozemulti@output\xa{\xa\clozelbrace\clozemulti@coding\clozerbrace}%
+ %\show\moodle@clozemulti@output
\xa\gdef\xa\htmlize@afteraction@hook\xa{\moodle@clozemulti@output}%
\def\endclozemulti@code{\htmlize@patchendenvironment}%
\else
%LaTeX version
\moodle@questionheader% %Any introductory text just continues to be typeset.
+ \par
+ \noindent
+ \moodle@makelatextag@qtype{multi}
+ \ifmoodle@handout\else
+ \moodle@makelatextag@value{default grade}{\moodle@marks{\csname moodle@default grade\endcsname}}
+ \moodle@makelatextag@multi
+ \fi
\def\cloze@multichoice@table@text{}%
+ \ifmoodle@handout\NewList{answerlist}\fi
+ %\let\moodle@feedback=\@empty
\loopthroughitemswithcommand{\moodle@print@clozemultichoice@answer}%
+ \ifmoodle@handout
+ \ifmoodle@shuffle
+ \let\moodle@clozemult@loop=\ForEachRandomItem
+ \else
+ \let\moodle@clozemult@loop=\ForEachFirstItem
+ \fi
+ \moodle@clozemult@loop{answerlist}{Answer}{
+ \xdef\cloze@multichoice@table@text{\expandonce\cloze@multichoice@table@text\expandonce\Answer}%
+ }%
+ \fi
\ifcase\moodle@multi@mode\relax
%Case 0: dropdown box style
- \begin{tabular}[t]{|l|}\firsthline% (\firsthline is from the array package.)
+ \par\noindent
+ \ifmoodle@handout
+ \begin{tabular}[t]{|p{.45\linewidth}|}
+ \else
+ \begin{tabular}[t]{|p{.45\linewidth}|p{.45\linewidth}|}
+ \fi
+ \firsthline% (\firsthline is from the array package.)
\cloze@multichoice@table@text%
\end{tabular}%
+ \par%
\or
%Case 1: vertical style
+ \par\noindent
\begin{itemize}\setlength\itemsep{0pt}\setlength\parskip{0pt}%
\cloze@multichoice@table@text%
\end{itemize}%
+ \par%
\else
%Case 2: horizontal radio buttons
\par{\cloze@multichoice@table@text}\par%
@@ -1025,40 +1838,75 @@
}[\endclozemulti@code]%
\def\moodle@print@clozemultichoice@answer#1{%
- \moodle@print@clozemultichoice@answer@int#1\@rdelim%
+ \let\moodle@feedback=\@empty
+ \moodle@print@clozemultichoice@answer@int#1 \@rdelim%
}%
\newcommand\moodle@print@clozemultichoice@answer@int[1][]{%
+ \setkeys{moodle}{fraction=0,#1}%
\moodle@print@clozemultichoice@answer@int@int%
}%
\def\moodle@print@clozemultichoice@answer@int@int#1#2\@rdelim{%
+ \def\moodle@answertext{}%
% Case 0: "(answer) \\ \hline"
% Case 1: "\item (answer)"
% Case 2: "$\bullet~$(answer)\hfill"
\ifcase\moodle@multi@mode\relax
\relax% Case 0
\or
- \g@addto@macro\cloze@multichoice@table@text{\item}% Case 1
+ \g@addto@macro\moodle@answertext{\item}% Case 1
\else
- \g@addto@macro\cloze@multichoice@table@text{$\bullet~$}% Case 2
+ \g@addto@macro\moodle@answertext{$\bullet~$}% Case 2
\fi
\def\test@i{#1}%
\ifx\test@i\@star
- \g@addto@macro\cloze@multichoice@table@text{#2$~\checkmark$}%
+ \setkeys{moodle}{fraction=100}%
+ \g@addto@macro\moodle@answertext{#2}%
\else
- \g@addto@macro\cloze@multichoice@table@text{#1#2}%
+ \g@addto@macro\moodle@answertext{#1#2}%
+ \fi
+ \trim@spaces@in\moodle@answertext
+ \trim@spaces@in\moodle@answertext
+ \ifmoodle@handout\else
+ \ifx\moodle@fraction\@hundred
+ \g@addto@macro\moodle@answertext{$~\checkmark$}%
+ \else
+ \moodle@checkfraction
+ \ifdim0pt=\moodle@fraction pt\relax\else
+ \xdef\moodle@answertext{\expandonce\moodle@answertext$~(\moodle@fraction\%)$}%
+ \fi
+ \fi
\fi
\ifcase\moodle@multi@mode\relax
- \g@addto@macro{\cloze@multichoice@table@text}{\\ \hline}% Case 0
- \or
- \relax% Case 1
+ % Case 0
+ \ifmoodle@handout\else
+ \xdef\moodle@answertext{\expandonce\moodle@answertext &\expandonce\emph{\expandonce\moodle@feedback}}%
+ \fi
+ \g@addto@macro\moodle@answertext{\\\hline}
+ \or % Case 1
+ \ifmoodle@handout\else
+ \ifx\moodle@feedback\@empty\relax\else
+ \xdef\moodle@answertext{\expandonce\moodle@answertext \hfill \expandonce\emph{$\rightarrow$ \expandonce\moodle@feedback}}%
+ \fi
+ \fi
+ \else % otherwise
+ \ifmoodle@handout\else
+ \ifx\moodle@feedback\@empty\relax\else
+ \xdef\moodle@answertext{\expandonce\moodle@answertext\,\expandonce\emph{$\rightarrow$ \expandonce\moodle@feedback}}%
+ \fi
+ \fi
+ \g@addto@macro\moodle@answertext{\hfill}% Case 2
+ \fi
+ \ifmoodle@handout
+ \def\temp{\InsertLastItem{answerlist}}%
+ \xa\temp\xa{\moodle@answertext}%
\else
- \g@addto@macro{\cloze@multichoice@table@text}{\hfill}% Case 2
+ \xdef\cloze@multichoice@table@text{\expandonce\cloze@multichoice@table@text\expandonce\moodle@answertext}%
\fi
}%
\def\saveclozemultichoiceanswer#1{%
\bgroup
- \saveclozemultichoiceanswer@int#1\moodle@answer@rdelim
+ \saveclozemultichoiceanswer@int#1 \moodle@answer@rdelim
\egroup
}%
\newcommand\saveclozemultichoiceanswer@int[1][]{%
@@ -1077,17 +1925,18 @@
\def\moodle@answertext{#1#2}%
\fi
\trim@spaces@in\moodle@answertext
+ \trim@spaces@in\moodle@answertext
\ifx\moodle@fraction\@hundred
\g@addto@macro\clozemulti@coding{=}%
- \fi
- \ifnum0<\moodle@fraction\relax
- \ifnum\moodle@fraction<100\relax
+ \else
+ \moodle@checkfraction
+ \ifdim0pt=\moodle@fraction pt\relax\else
\xdef\clozemulti@coding{\expandonce\clozemulti@coding\otherpercent\moodle@fraction\otherpercent}%
\fi
\fi
\xdef\clozemulti@coding{\expandonce\clozemulti@coding\expandonce\moodle@answertext}%
\ifx\moodle@feedback\@empty\else
- \xdef\clozemulti@coding{\expandonce\clozemulti@coding\otherbackslash\otherhash\moodle@feedback}%
+ \xdef\clozemulti@coding{\expandonce\clozemulti@coding\otherbackslash\otherhash\expandonce\moodle@feedback}%
\fi
}%
\NewEnviron{clozenumerical}[1][]{%
@@ -1101,23 +1950,34 @@
\def\moodle@clozenumerical@output{}%
\xa\g@addto@macro\xa\moodle@clozenumerical@output\xa{\moodle@questionheader}%
\def\clozenumerical@coding{}%
- \edef\clozenumerical@coding{\otherlbrace\csname moodle@default grade\endcsname:NUMERICAL:}%
+ \edef\clozenumerical@coding{\csname moodle@default grade\endcsname:NUMERICAL:}%
\bgroup
\setkeys{moodle}{feedback={}}%
\loopthroughitemswithcommand{\saveclozenumericalanswer}%
\egroup
- \xa\g@addto@macro\xa\clozenumerical@coding\xa{\otherrbrace}%
- \xa\g@addto@macro\xa\moodle@clozenumerical@output\xa{\clozenumerical@coding}%
+ %\xa\g@addto@macro\xa\clozenumerical@coding\xa{\otherrbrace}%
+ \xa\g@addto@macro\xa\moodle@clozenumerical@output\xa{\xa\clozelbrace\clozenumerical@coding\clozerbrace}%
\xa\gdef\xa\htmlize@afteraction@hook\xa{\moodle@clozenumerical@output}%
\def\endclozenumerical@code{\htmlize@patchendenvironment}%
\else
%LaTeX version
\moodle@questionheader% %Any introductory text just continues to be typeset.
- \def\cloze@numerical@table@text{}%
- \loopthroughitemswithcommand{\moodle@print@clozenumerical@answer}%
- \begin{tabular}[t]{|ll|}\firsthline
- \cloze@numerical@table@text\hline%
- \end{tabular}%
+ \par
+ \noindent
+ \moodle@makelatextag@qtype{numerical}
+ \ifmoodle@handout\else
+ \moodle@makelatextag@value{default grade}{\moodle@marks{\csname moodle@default grade\endcsname}}
+ \moodle@makelatextag@numerical
+ \par
+ \noindent
+ \def\cloze@numerical@table@text{}%
+ \loopthroughitemswithcommand{\moodle@print@clozenumerical@answer}%
+ \begin{tabular}[t]{|p{.45\linewidth}|p{.45\linewidth}|}
+ \firsthline% (\firsthline is from the array package.)
+ \cloze@numerical@table@text%
+ \end{tabular}%
+ \par%
+ \fi
\def\endclozenumerical@code{\relax}%
\fi
\passvalueaftergroup\endclozenumerical@code%
@@ -1126,6 +1986,7 @@
}[\endclozenumerical@code]%
\def\moodle@print@clozenumerical@answer#1{%
+ \let\moodle@feedback=\@empty
\bgroup
\moodle@print@clozenumerical@answer@int#1\@rdelim
\egroup
@@ -1136,17 +1997,23 @@
}%
\def\moodle@print@clozenumerical@answer@int@int#1\@rdelim{%
\ifx\moodle@fraction\@hundred
- \def\moodle@clozenumericalprint@fraction{$\checkmark$}%
+ \def\moodle@clozenumericalprint@fraction{$~\checkmark$}%
\else
- \edef\moodle@clozenumericalprint@fraction{(\moodle@fraction\%)}%
+ \moodle@checkfraction
+ \edef\moodle@clozenumericalprint@fraction{$(~\moodle@fraction\%)$}%
\fi
- \ifdim0pt=\moodle@tolerance pt\relax
+ \ifnum\z@=\moodle@tolerance
\def\moodle@clozenumericalprint@tolerance{}%
\else
- \edef\moodle@clozenumericalprint@tolerance{\noexpand\pm\moodle@tolerance}%
+ \edef\moodle@clozenumericalprint@tolerance{$\,\pm\,$\moodle@printnum{\moodle@tolerance}}%
+ \fi
+ \xdef\test@i{\trim@spaces{#1}}%
+ \ifx\test@i\@star
+ \xdef\moodle@clozenumericalprint@line{#1~\moodle@clozenumericalprint@fraction & \expandonce\emph{\expandonce\moodle@feedback}}%
+ \else
+ \xdef\moodle@clozenumericalprint@line{\moodle@printnum{#1}\moodle@clozenumericalprint@tolerance~\moodle@clozenumericalprint@fraction & \expandonce\emph{\expandonce\moodle@feedback}}%
\fi
- \xdef\moodle@clozenumericalprint@line{$#1\moodle@clozenumericalprint@tolerance$ & \moodle@clozenumericalprint@fraction}%
- \xa\g@addto@macro\xa\cloze@numerical@table@text\xa{\moodle@clozenumericalprint@line \\}%
+ \xa\g@addto@macro\xa\cloze@numerical@table@text\xa{\moodle@clozenumericalprint@line \\\hline}%
}%
\def\saveclozenumericalanswer#1{%
@@ -1166,15 +2033,20 @@
\trim@spaces@in\moodle@answertext
\ifx\moodle@fraction\@hundred
\g@addto@macro\clozenumerical@coding{=}%
- \fi
- \ifnum0<\moodle@fraction\relax
- \ifnum\moodle@fraction<100\relax
+ \else
+ \moodle@checkfraction
+ \ifdim0pt=\moodle@fraction pt\relax\else
\xdef\clozenumerical@coding{\expandonce\clozenumerical@coding\otherpercent\moodle@fraction\otherpercent}%
\fi
\fi
- \xdef\clozenumerical@coding{\expandonce\clozenumerical@coding\moodle@answertext:\moodle@tolerance}%
+ \ifx\moodle@answertext\@star
+ \xdef\clozenumerical@coding{\expandonce\clozenumerical@coding\moodle@answertext}%
+ \else
+ \xdef\clozenumerical@coding{\expandonce\clozenumerical@coding\moodle@answertext:\moodle@tolerance}%
+ \fi
\ifx\moodle@feedback\@empty\else
- \xdef\clozenumerical@coding{\expandonce\clozenumerical@coding\otherbackslash\otherhash\moodle@feedback}%
+ %\trim@spaces@in\moodle@feedback
+ \xdef\clozenumerical@coding{\expandonce\clozenumerical@coding\otherbackslash\otherhash\expandonce\moodle@feedback}%
\fi
}%
\NewEnviron{clozeshortanswer}[1][]{%
@@ -1196,29 +2068,37 @@
\xa\g@addto@macro\xa\moodle@clozeshortanswer@output\xa{\moodle@questionheader}%
\def\clozeshortanswer@coding{}%
\ifnum\count0=1\relax
- \edef\clozeshortanswer@coding{\otherlbrace\csname moodle@default grade\endcsname:SHORTANSWER_C:}%
+ \edef\clozeshortanswer@coding{\csname moodle@default grade\endcsname:SHORTANSWER_C:}%
\else
- \edef\clozeshortanswer@coding{\otherlbrace\csname moodle@default grade\endcsname:SHORTANSWER:}%
+ \edef\clozeshortanswer@coding{\csname moodle@default grade\endcsname:SHORTANSWER:}%
\fi
\bgroup
\setkeys{moodle}{feedback={}}%
\loopthroughitemswithcommand{\saveclozeshortansweranswer}%
\egroup
- \xa\g@addto@macro\xa\clozeshortanswer@coding\xa{\otherrbrace}%
- \xa\g@addto@macro\xa\moodle@clozeshortanswer@output\xa{\clozeshortanswer@coding}%
+ %\xa\g@addto@macro\xa\clozeshortanswer@coding\xa{\otherrbrace}%
+ \xa\g@addto@macro\xa\moodle@clozeshortanswer@output\xa{\xa\clozelbrace\clozeshortanswer@coding\clozerbrace}%
\xa\gdef\xa\htmlize@afteraction@hook\xa{\moodle@clozeshortanswer@output}%
\def\endclozeshortanswer@code{\htmlize@patchendenvironment}%
\else
%LaTeX version
\moodle@questionheader% %Any introductory text just continues to be typeset.
- \def\cloze@shortanswer@table@text{}%
- \loopthroughitemswithcommand{\moodle@print@clozeshortanswer@answer}%
- \ifnum\count0=1\relax
- \marginpar{\tiny\mbox{(Case-Sensitive)}}%
+ \par
+ \noindent
+ \moodle@makelatextag@qtype{shortanswer}
+ \ifmoodle@handout\else
+ \moodle@makelatextag@value{default grade}{\moodle@marks{\csname moodle@default grade\endcsname}}
+ \moodle@makelatextag@shortanswer
+ \par
+ \noindent
+ \def\cloze@shortanswer@table@text{}%
+ \loopthroughitemswithcommand{\moodle@print@clozeshortanswer@answer}%
+ \begin{tabular}[t]{|p{.45\linewidth}|p{.45\linewidth}|}
+ \firsthline% (\firsthline is from the array package.)
+ \cloze@shortanswer@table@text%
+ \end{tabular}%
+ \par%
\fi
- \begin{tabular}[t]{|ll|}\firsthline
- \cloze@shortanswer@table@text\hline%
- \end{tabular}%
\def\endclozeshortanswer@code{\relax}%
\fi
\passvalueaftergroup\endclozeshortanswer@code%
@@ -1227,6 +2107,7 @@
}[\endclozeshortanswer@code]%
\def\moodle@print@clozeshortanswer@answer#1{%
+ \let\moodle@feedback=\@empty
\bgroup
\moodle@print@clozeshortanswer@answer@int#1\@rdelim
\egroup
@@ -1237,12 +2118,13 @@
}%
\def\moodle@print@clozeshortanswer@answer@int@int#1\@rdelim{%
\ifx\moodle@fraction\@hundred
- \def\moodle@clozeshortanswerprint@fraction{$\checkmark$}%
+ \def\moodle@clozeshortanswerprint@fraction{$~\checkmark$}%
\else
- \edef\moodle@clozeshortanswerprint@fraction{(\moodle@fraction\%)}%
+ \moodle@checkfraction
+ \edef\moodle@clozeshortanswerprint@fraction{$~(\moodle@fraction\%)$}%
\fi
- \xdef\moodle@clozeshortanswerprint@line{#1 & \moodle@clozeshortanswerprint@fraction}%
- \xa\g@addto@macro\xa\cloze@shortanswer@table@text\xa{\moodle@clozeshortanswerprint@line \\}%
+ \xdef\moodle@clozeshortanswerprint@line{#1~\moodle@clozeshortanswerprint@fraction & \expandonce\emph{\expandonce\moodle@feedback}}%
+ \xa\g@addto@macro\xa\cloze@shortanswer@table@text\xa{\moodle@clozeshortanswerprint@line \\\hline}%
}%
\def\saveclozeshortansweranswer#1{%
@@ -1262,15 +2144,15 @@
\trim@spaces@in\moodle@answertext
\ifx\moodle@fraction\@hundred
\g@addto@macro\clozeshortanswer@coding{=}%
- \fi
- \ifnum0<\moodle@fraction\relax
- \ifnum\moodle@fraction<100\relax
+ \else
+ \moodle@checkfraction
+ \ifdim0pt=\moodle@fraction pt\relax\else
\xdef\clozeshortanswer@coding{\expandonce\clozeshortanswer@coding\otherpercent\moodle@fraction\otherpercent}%
\fi
\fi
\xdef\clozeshortanswer@coding{\expandonce\clozeshortanswer@coding\moodle@answertext}%
\ifx\moodle@feedback\@empty\else
- \xdef\clozeshortanswer@coding{\expandonce\clozeshortanswer@coding\otherbackslash\otherhash\moodle@feedback}%
+ \xdef\clozeshortanswer@coding{\expandonce\clozeshortanswer@coding\otherbackslash\otherhash\expandonce\moodle@feedback}%
\fi
}%
{\catcode`\#=12\gdef\otherhash{#}%
@@ -1278,14 +2160,20 @@
\catcode`\&=12\gdef\otherampersand{&}%
\catcode`\^=12\gdef\othercaret{^}%
\catcode`\$=12\gdef\otherdollar{$}%
- \catcode`\%=12\gdef\otherpercent{%}}%
+ \catcode`\%=12\gdef\otherpercent{%}
+ \catcode`\%=12\gdef\otherlbracket{[}
+ \catcode`\%=12\gdef\otherrbracket{]}}%
{\catcode`\ =12\gdef\otherspace{ }}%
-{\tt\catcode`\|=0\catcode`\\=12\relax|gdef|otherbackslash{\}}%
+{\ttfamily\catcode`\|=0\catcode`\\=12\relax|gdef|otherbackslash{\}}%
{\catcode`\[=1\catcode`\]=2\catcode`\{=12\catcode`\}=12%
- \gdef\otherlbrace[{]\gdef\otherrbrace[}]]
+ \gdef\otherlbrace[{]\gdef\otherrbrace[}]\gdef\clozelbrace[{]\gdef\clozerbrace[}]]%
\edef\@otherlbrace{\otherlbrace}%
\edef\@otherrbrace{\otherrbrace}%
+\edef\@otherlbracket{\otherlbracket}%
+\edef\@otherrbracket{\otherrbracket}%
+\edef\@clozelbrace{\clozelbrace}%
+\edef\@clozerbrace{\clozerbrace}%
\edef\@otherdollar{\otherdollar}%
\edef\@otherbackslash{\otherbackslash}%
\edef\@othertilde{\othertilde}%
@@ -1362,6 +2250,7 @@
\def\retokenizenormal@to@macro#1#2{%
\scantokens@to@macro#1{\retokenizingcatcodes}{#2}%
}%
+\newcount\grouplevel
\newcount\moodle@mathmodedepth
\moodle@mathmodedepth=0\relax
\def\moodle@ifmathmode#1#2{%
@@ -1370,18 +2259,18 @@
\else
#2%
\fi
-}
-
-\newcount\grouplevel
+}%
+\newcount\moodle@listdepth
+\moodle@listdepth=0\relax
-\newif\ifhtmlizer@active
-\htmlizer@activefalse
\long\def\htmlize@grabblock#1#2\htmlize@rdelim@ii{%
\long\def\htmlize@blockinbraces{#1}%
\long\def\htmlize@remainder{#2}%
}%
\ultradetokenize@to@macro\@htmlize@stop@detokenized{\@htmlize@stop}%
\xa\def\xa\htmlize@remove@stopcode\xa#\xa1\@htmlize@stop@detokenized{#1}%
+\newif\ifhtmlizer@active
+\htmlizer@activefalse
\newif\ifhtmlize@actioncs
\newif\ifhtmlize@expandcs
\newif\ifhtmlize@passcs
@@ -1402,7 +2291,7 @@
\advance\grouplevel by 1\relax
\bgroup
\ultradetokenize@to@macro\htmlize@texttoscan{#1}%
- \xa\htmlize@recursive@i\htmlize@texttoscan\@htmlize@stop\@htmlize@stop\@htmlize@stop\htmlize@rdelim@i
+ \xa\htmlize@recursive@i\htmlize@texttoscan\@htmlize@stop\@htmlize@stop\@htmlize@stop\htmlize@rdelim@i%
\egroup
\advance\grouplevel by -1\relax
}%
@@ -1448,7 +2337,11 @@
\gdef\htmlize@scrap{\converttohtml@int}%
\xa\g@addto@macro\xa\htmlize@scrap\xa{\xa{\htmlize@blockinbraces}}%
\g@addto@macro\htmlize@scrap{\g@addto@macro\htmlize@output}%
- \xa\g@addto@macro\xa\htmlize@scrap\xa{\xa{\otherrbrace}}%
+ \ifmoodle@clozemode
+ \xa\g@addto@macro\xa\htmlize@scrap\xa{\xa{\otherbackslash\otherrbrace}}%
+ \else
+ \xa\g@addto@macro\xa\htmlize@scrap\xa{\xa{\otherrbrace}}%
+ \fi
\g@addto@macro\htmlize@scrap{\htmlize@recursive@i}%
\xa\g@addto@macro\xa\htmlize@scrap\xa{\htmlize@remainder@detokenized\@htmlize@stop\@htmlize@stop\@htmlize@stop\htmlize@rdelim@i}%
% Okay, that's done. It's stored in a global macro.
@@ -1465,10 +2358,10 @@
\htmlize@displaymathshift@replace#1#2#3\htmlize@rdelim@iii%
\else
% Single dollar sign, so we're entering inline math mode.
- % We grab everything between $$...$$, sanitize it, and add it verbatim to
+ % We grab everything between $...$, sanitize it, and add it verbatim to
% our output.
\htmlize@inlinemathshift@replace#1#2#3\htmlize@rdelim@iii%
- \fi
+ \fi% \ifx\test@ii\@otherdollar
% Now we resume work.
% The \htmlize@xxxxxxmathshift@replace macro stored the remaining text in \htmlize@remaining@text.
% Note that since we never detokenized and retokenized #1#2#3,
@@ -1593,9 +2486,9 @@
%\edef\ds{Must pass on \xa\string\@htmlize@cs}\show\ds
\g@addto@macro\htmlize@output{#1}%
\def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
- \fi
- \fi
- \fi
+ \fi% \ifhtmlize@expandcs
+ \fi% \ifhtmlize@actioncs
+ \fi% \ifx\@htmlize@cs\@@begin@cs
\else%
\ifx\test@i\@othertilde%
% The ~ becomes non-breaking space &nbsp;
@@ -1610,7 +2503,7 @@
\else
\g@addto@macro\htmlize@output{\otherampersand lsquo;}%
\def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
- \fi
+ \fi% \ifx\test@ii\@lsinglequote%
\else
\ifx\test@i\@rsinglequote%
\ifx\test@ii\@rsinglequote%
@@ -1620,7 +2513,7 @@
\else
\g@addto@macro\htmlize@output{\otherampersand rsquo;}%
\def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
- \fi
+ \fi% \ifx\test@ii\@rsinglequote%
\else
\ifx\test@i\@doublequote
\g@addto@macro\htmlize@output{\otherampersand rdquo;}%
@@ -1639,16 +2532,16 @@
% Default case: write first token to output, call self on remaining tokens.
\g@addto@macro\htmlize@output{#1}%
\def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
- \fi
- \fi
- \fi
- \fi
- \fi
- \fi
- \fi
- \fi
- \fi
- \fi
+ \fi% \ifx\test@i\@gt
+ \fi% \ifx\test@i\@lt
+ \fi% \ifx\test@i\@doublequote
+ \fi% \ifx\test@i\@rsinglequote%
+ \fi% \ifx\test@i\@lsinglequote%
+ \fi% \ifx\test@i\@othertilde%
+ \fi% \ifx\test@i\@otherbackslash%
+ \fi% \ifx\test@i\@otherdollar%
+ \fi% \ifx\test@i\@otherlbrace%
+ \fi% \ifx\test@i\@@htmlize@stop
\htmlize@next@i
}%
@@ -1658,16 +2551,38 @@
\edef\inlinemathleftdelim{\otherbackslash(}%
\def\inlinemathrightdelim#1{\advancemathmodecounter{-1}%
\g@addto@macro\htmlize@output{\otherbackslash)}}%
-\edef\displaymathleftdelim{<CENTER>\otherbackslash[}%
+\edef\displaymathleftdelim{\otherbackslash[}%
\def\displaymathrightdelim#1{\advancemathmodecounter{-1}%
- \g@addto@macro\htmlize@output{\otherbackslash]</CENTER>}}%
+ \g@addto@macro\htmlize@output{\otherbackslash]}}%
+\long\def\htmlize@inlinemath@recursive@i#1#2#3\htmlize@rdelim@i{%
+ % inspired by \htmlize@recursive@i
+ \def\test@i{#1}%
+ \ifx\test@i\@@htmlize@stop
+ \let\htmlize@next@i=\relax
+ \else
+ \ifx\test@i\@otherbackslash
+ \g@addto@macro\mathtext{#1#2}%
+ \def\htmlize@next@i{\xa\htmlize@inlinemath@recursive@i#3\htmlize@rdelim@i}%
+ \else
+ \ifx\test@i\@otherdollar
+ \let\htmlize@next@i=\relax
+ \g@addto@macro\aftertext{#2#3}%
+ \else
+ \g@addto@macro\mathtext{#1}%
+ \def\htmlize@next@i{\xa\htmlize@inlinemath@recursive@i#2#3\htmlize@rdelim@i}%
+ \fi
+ \fi
+ \fi
+ \htmlize@next@i
+}
{\catcode`\$=12\relax%
- \gdef\htmlize@inlinemathshift@replace$#1$#2\htmlize@rdelim@iii{%
+ \gdef\htmlize@inlinemathshift@replace#1#2\htmlize@rdelim@iii{%
%\def\ds{inline math shift has '#1' and '#2'}\show\ds
\xa\g@addto@macro\xa\htmlize@output\xa{\inlinemathleftdelim}%
\advancemathmodecounter{1}%
- \def\mathtext{#1}%
- \def\aftertext{#2}%
+ \gdef\mathtext{}%
+ \gdef\aftertext{}%
+ \htmlize@inlinemath@recursive@i#2\htmlize@rdelim@i%
\xdef\htmlize@remaining@text{\expandonce\mathtext%
\otherbackslash inlinemathrightdelim{}%
\expandonce\aftertext}%
@@ -1683,6 +2598,7 @@
\expandonce\aftertext}%
}%
}
+
\long\def\htmlize@do@actionenv#1#2\@htmlize@stop\htmlize@actionsequence@rdelim{%
\bgroup %The corresponding \egroup is given in \htmlize@proceedwiththerest,
%to localize the changes to the environment definitions.
@@ -1760,11 +2676,41 @@
\xa\g@addto@macro\xa\htmlize@activate@css\xa{\htmlize@scrap}%
\xa\def\csname html@\string#1\endcsname% %And this \def\html@\oldcsname is follows by the remainder of the definition.
}
+\def\html@action@newcommand#1[#2][#3]#4{%
+ %\message{>>> Defining #1[#2][#3]{...} ^^J}
+ \ifmoodle@draftmode
+ \else
+ \xa\html@action@def\csname #1\endcsname{\csname moodle@#1@int\endcsname}%
+ \fi
+ % Note that \htmlize@do@actioncs will 'patch' this by putting
+ % '\xa\htmlize@proceedwiththerest\htmlize@afteraction@hook'
+ % at the end. We want those 3 tokens to occur instead after
+ % the graphics filename.
+ \xa\csdef{moodle@#1@int}##1##2##3{\csname moodle@#1@int@int\endcsname}%
+ % This gobbles up those three spurious tokens,
+ % which we will re-insert after our work is done.
+ \xa\newcommand\csname moodle@#1@int@int\endcsname[#2][#3]{%
+ #4%
+ % Now we re-insert the code to get the HTMLizing going again.
+ \xa\htmlize@proceedwiththerest\htmlize@afteraction@hook
+ }%
+}
\def\htmlize@redefine@expansionmacros{}%
\long\def\htmlize@record@expand#1{%
\xa\listadd\xa\htmlize@cs@expandlist\xa{\string#1}%
}
\let\htmlregister=\htmlize@record@expand
+\def\moodleregisternewcommands{%
+ %% INSPIRED FROM
+ %https://tex.stackexchange.com/questions/73271/how-to-redefine-or-patch-the-newcommand-command
+ \newcommand*{\saved@ifdefinable}{}
+ \let\saved@ifdefinable\@ifdefinable
+ \renewcommand{\@ifdefinable}[2]{%
+ \saved@ifdefinable{##1}{##2}%
+ \htmlregister{##1}
+ }%
+ \let\@@ifdefinable\@ifdefinable
+}%
\long\def\html@def#1{%
\htmlize@record@expand{#1}%
\xa\def\xa\htmlize@scrap\xa{\xa\let\xa#1\csname html@\string#1\endcsname}%
@@ -1779,27 +2725,64 @@
\htmlize@record@environment{shortanswer}
\html@newenvironment{center}{\xdef\htmlize@afteraction@hook{<CENTER>\expandonce\BODY</CENTER>}}%
-\html@newenvironment{enumerate}{%
- \xa\gatheritems\xa{\BODY}%
- \gdef\htmlize@afteraction@hook{<OL>}%
- \loopthroughitemswithcommand{\moodle@itemtoLI}%
- \g@addto@macro\htmlize@afteraction@hook{</OL>}%
-}%
-\html@newenvironment{itemize}{%
- \xa\gatheritems\xa{\BODY}%
- \gdef\htmlize@afteraction@hook{<UL>}%
- \loopthroughitemswithcommand{\moodle@itemtoLI}%
- \g@addto@macro\htmlize@afteraction@hook{</UL>}%
+
+\def\moodle@save@getitems@state{%
+ \global\xa\xdef\csname moodle@currentitemnumber@level@\the\moodle@listdepth\xa\endcsname\xa{\thecurrentitemnumber}%
+ \global\xa\xdef\csname moodle@numgathereditems@level@\the\moodle@listdepth\xa\endcsname\xa{\thenumgathereditems}%
+ \moodle@saveitems{\thenumgathereditems}%
+}%
+\def\moodle@restore@getitems@state{%
+ \setcounter{numgathereditems}{\csname moodle@numgathereditems@level@\the\moodle@listdepth\endcsname}%
+ \setcounter{currentitemnumber}{\csname moodle@currentitemnumber@level@\the\moodle@listdepth\endcsname}%
+ \moodle@restoreitems{\thenumgathereditems}%
+}%
+\def\moodle@saveitems#1{%
+ \ifnum#1>0%
+ \global\csletcs{moodle@level@\the\moodle@listdepth @item@#1}{getitems@item@#1}%
+ \xa\moodle@saveitems\xa{\number\numexpr#1-1\expandafter}%
+ \fi
+}%
+\def\moodle@restoreitems#1{%
+ \ifnum#1>0%
+ \global\csletcs{getitems@item@#1}{moodle@level@\the\moodle@listdepth @item@#1}%
+ \global\xa\let\csname moodle@level@\the\moodle@listdepth @item@#1\endcsname=\@undefined
+ \xa\moodle@restoreitems\xa{\number\numexpr#1-1\expandafter}%
+ \fi
+}%
+\def\moodle@makelistenv#1#2{%
+ \html@newenvironment{#1}{%
+ \advance\moodle@listdepth by 1\relax
+ \moodle@save@getitems@state%
+ \xa\gatheritems\xa{\BODY}%
+ \gdef\htmlize@afteraction@hook{<#2>}%
+ \loopthroughitemswithcommand{\moodle@itemtoLI}%
+ \g@addto@macro\htmlize@afteraction@hook{</#2>}%
+ \moodle@restore@getitems@state%
+ \advance\moodle@listdepth by -1\relax
+ }%
}%
+
+\moodle@makelistenv{enumerate}{OL}%
+\moodle@makelistenv{itemize}{UL}%
+
\def\moodle@itemtoLI#1{%
- \g@addto@macro\htmlize@afteraction@hook{<LI>#1</LI>}%
+ \g@addto@macro\htmlize@afteraction@hook{<LI>#1}%
+ \trim@spaces@in\htmlize@afteraction@hook%
+ \g@addto@macro\htmlize@afteraction@hook{</LI>}%
}%
\def\advancemathmodecounter#1{%
\global\advance\moodle@mathmodedepth by #1\relax
}
+\def\openclozemode{%
+ \global\moodle@clozemodetrue\relax
+}
+\def\endclozemode{%
+ \global\moodle@clozemodefalse\relax
+}
\htmlize@record@action{\advancemathmodecounter}%
-
+\htmlize@record@action{\openclozemode}%
+\htmlize@record@action{\endclozemode}%
\htmlize@record@action{\relax}%
\html@action@def\#{\g@addto@macro\htmlize@output{\otherhash}}%
@@ -1812,15 +2795,32 @@
}%
\html@action@def\}{%
\moodle@ifmathmode{\g@addto@macro\htmlize@output{\otherbackslash\otherrbrace}}%
- {\g@addto@macro\htmlize@output{\otherrbrace}}%
+ {\ifmoodle@clozemode\g@addto@macro\htmlize@output{\otherbackslash}\fi
+ \g@addto@macro\htmlize@output{\otherrbrace}}%
+ }%
+\html@action@def\[{%
+ \advancemathmodecounter{1}
+ \g@addto@macro\htmlize@output{\otherbackslash\otherlbracket}%
+ }%
+\html@action@def\]{%
+ \g@addto@macro\htmlize@output{\otherbackslash\otherrbracket}%
+ \advancemathmodecounter{-1}
+ }%
+\html@action@def\({%
+ \advancemathmodecounter{1}
+ \g@addto@macro\htmlize@output{\otherbackslash(}%
+ }%
+\html@action@def\){%
+ \g@addto@macro\htmlize@output{\otherbackslash)}%
+ \advancemathmodecounter{-1}
}%
\html@action@def\ldots{%
\moodle@ifmathmode{\g@addto@macro\htmlize@output{\string\ldots}}%
- {\g@addto@macro\htmlize@output{...}}%
+ {\g@addto@macro\htmlize@output{\otherampersand hellip\othersemicol}}%
}%
\html@action@def\dots{%
\moodle@ifmathmode{\g@addto@macro\htmlize@output{\string\dots}}%
- {\g@addto@macro\htmlize@output{...}}%
+ {\g@addto@macro\htmlize@output{\otherampersand hellip\othersemicol}}%
}%
\html@action@def\ {%
\moodle@ifmathmode{\g@addto@macro\htmlize@output{\otherbackslash\otherspace}}%
@@ -1829,10 +2829,25 @@
\html@action@def\${%
\g@addto@macro\htmlize@output{\otherdollar}%
}%
-
\html@action@def\clozetilde{%
\xa\g@addto@macro\xa\htmlize@output\xa{\othertilde}%
}%
+\html@action@def\clozelbrace{%
+ \openclozemode
+ \xa\g@addto@macro\xa\htmlize@output\xa{\otherlbrace}%
+ }%
+\html@action@def\clozerbrace{%
+ \xa\g@addto@macro\xa\htmlize@output\xa{\otherrbrace}%
+ \endclozemode
+ }%
+\html@action@def\TeX{%
+ \g@addto@macro\htmlize@output{\otherbackslash(\otherbackslash rm\otherbackslash TeX\otherbackslash)}
+ }%
+\html@action@def\LaTeX{%
+ \g@addto@macro\htmlize@output{\otherbackslash(\otherbackslash rm\otherbackslash LaTeX\otherbackslash)}
+ }%
+
+{\catcode`;=12\relax\gdef\othersemicol{;}}
{\catcode`|=3\relax
\gdef\htmlize@vowels{a|e|i|o|u|A|E|I|O|U|}}
@@ -1841,31 +2856,38 @@
\g@addto@macro\htmlize@activate@css{%
\def#1##1{%
\ifinlist{##1}{\htmlize@vowels}%
- {\g@addto@macro\htmlize@output{\otherampersand##1#2;}}%
+ {\g@addto@macro\htmlize@output{\otherampersand##1#2\othersemicol}}%
{\xa\g@addto@macro\htmlize@output\xa{\string#1##1}}%
}%
}%
}
\htmlize@define@diacritic{\^}{circ}%
\htmlize@define@diacritic{\'}{acute}%
-\htmlize@define@diacritic{\"}{uml}%
\htmlize@define@diacritic{\`}{grave}%
+{\catcode`|=3\relax
+ \gdef\htmlize@diaeresis{a|e|i|o|u|y|A|E|I|O|U|Y|}}
+\html@action@def\"#1{%
+ \ifinlist{#1}{\htmlize@diaeresis}%
+ {\g@addto@macro\htmlize@output{\otherampersand#1uml\othersemicol}}%
+ {\xa\g@addto@macro\htmlize@output\xa{\string\"#1}}%
+}%
+
\def\@o{o}\def\@O{O}\def\@u{u}\def\@U{U}%
\html@action@def\H#1{%
\bgroup
\def\test@i{#1}%
\ifx\test@i\@O
- \def\toadd{\otherampersand\otherhash337;}%
+ \def\toadd{\otherampersand\otherhash336\othersemicol}%
\else
\ifx\test@i\@o
- \def\toadd{\otherampersand\otherhash337;}%
+ \def\toadd{\otherampersand\otherhash337\othersemicol}%
\else
- \ifx\test@i\U
- \def\toadd{\otherampersand\otherhash368;}%
+ \ifx\test@i\@U
+ \def\toadd{\otherampersand\otherhash368\othersemicol}%
\else
- \ifx\test@i\u
- \def\toadd{\otherampersand\otherhash369;}%
+ \ifx\test@i\@u
+ \def\toadd{\otherampersand\otherhash369\othersemicol}%
\else
\def\toadd{\otherbackslash\otherlbrace#1\otherrbrace}%
\fi
@@ -1876,37 +2898,234 @@
\egroup
}%
+\def\@c{c}\def\@C{C}\def\@s{s}\def\@S{S}\def\@t{t}\def\@T{T}%
+\html@action@def\c#1{%
+\bgroup
+ \def\test@i{#1}%
+ \ifx\test@i\@c
+ \def\toadd{\otherampersand ccedil\othersemicol}%
+ \else
+ \ifx\test@i\@C
+ \def\toadd{\otherampersand Ccedil\othersemicol}%
+ \else
+ \ifx\test@i\@s
+ \def\toadd{\otherampersand\otherhash351\othersemicol}%
+ \else
+ \ifx\test@i\@S
+ \def\toadd{\otherampersand\otherhash350\othersemicol}%
+ \else
+ \ifx\test@i\@t
+ \def\toadd{\otherampersand\otherhash355\othersemicol}%
+ \else
+ \ifx\test@i\@T
+ \def\toadd{\otherampersand\otherhash354\othersemicol}%
+ \else
+ \def\toadd{\otherbackslash\otherlbrace#1\otherrbrace}%
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \xa\g@addto@macro\xa\htmlize@output\xa{\toadd}%
+\egroup
+}%
+
{\catcode`|=3\relax
\gdef\htmlize@tilde{A|N|O|a|n|o|}}
\html@action@def\~#1{%
\ifinlist{#1}{\htmlize@tilde}%
- {\g@addto@macro\htmlize@output{\otherampersand#1tilde;}}%
+ {\g@addto@macro\htmlize@output{\otherampersand#1tilde\othersemicol}}%
{\xa\g@addto@macro\htmlize@output\xa{\string\~#1}}%
- }%
-\html@def\underline#1{<SPAN STYLE="text-decoration: underline;">#1</SPAN>}
+}%
+
+{\catcode`|=3\relax
+ \gdef\htmlize@breve{A|G|U|a|g|u|}}
+\def\@e{e}\def\@E{E}\def\@i{i}\def\@ii{\i}\def\@I{I}\def\@o{o}\def\@O{O}%
+\html@action@def\u#1{%
+ \ifinlist{#1}{\htmlize@breve}%
+ {\g@addto@macro\htmlize@output{\otherampersand#1breve\othersemicol}}%
+ {
+ \bgroup
+ \def\test@i{#1}%
+ \ifx\test@i\@E
+ \def\toadd{\otherampersand\otherhash276\othersemicol}%
+ \else
+ \ifx\test@i\@e
+ \def\toadd{\otherampersand\otherhash277\othersemicol}%
+ \else
+ \ifx\test@i\@I
+ \def\toadd{\otherampersand\otherhash300\othersemicol}%
+ \else
+ \ifx\test@i\@i
+ \def\toadd{\otherampersand\otherhash301\othersemicol}%
+ \else
+ \ifx\test@i\@ii
+ \def\toadd{\otherampersand\otherhash301\othersemicol}%
+ \else
+ \ifx\test@i\@O
+ \def\toadd{\otherampersand\otherhash334\othersemicol}%
+ \else
+ \ifx\test@i\@o
+ \def\toadd{\otherampersand\otherhash335\othersemicol}%
+ \else
+ \def\toadd{\otherbackslash\otherlbrace#1\otherrbrace}%
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \xa\g@addto@macro\xa\htmlize@output\xa{\toadd}%
+ \egroup
+ }%
+}%
+
+{\catcode`|=3\relax
+ \gdef\htmlize@caron{C|D|E|L|N|R|S|T|Z|c|d|e|l|n|r|s|t|z|}}
+\html@action@def\v#1{%
+ \ifinlist{#1}{\htmlize@caron}%
+ {\g@addto@macro\htmlize@output{\otherampersand#1caron\othersemicol}}%
+ {\xa\g@addto@macro\htmlize@output\xa{\string\v#1}}%
+}%
+\html@def\underline#1{<SPAN STYLE=\&\#34;text-decoration: underline;\&\#34;>#1</SPAN>}
\html@def\emph#1{<EM>#1</EM>}%
+\html@def\textit#1{<I>#1</I>}%
\html@def\textbf#1{<B>#1</B>}%
+\html@def\texttt#1{<CODE>#1</CODE>}%
+\html@def\textsc#1{<SPAN STYLE=\&\#34;font-variant: small-caps;\&\#34;>#1</SPAN>}
+\html@def\url#1{<A href=\&\#34;#1\&\#34;>#1</A>}%
+\html@def\href#1#2{<A href=\&\#34;#1\&\#34;>#2</A>}%
+\html@def\textsuperscript#1{<SUP>#1</SUP>}%
+\html@def\up#1{<SUP>#1</SUP>}%
+\html@def\fup#1{<SUP>#1</SUP>}%
+\html@def\textsubscript#1{<SUB>#1</SUB>}%
\html@def\blank{____________}%
\html@def\par{</P><P>}%
\html@def\aa{\&aring;}%
\html@def\AA{\&Aring;}%
\html@def\ae{\&aelig;}%
\html@def\AE{\&AElig;}%
+\html@def\oe{\&oelig;}%
+\html@def\OE{\&OElig;}%
\html@def\S{\&sect;}%
\html@def\euro{\&euro;}%
\html@def\texteuro{\&euro;}%
\html@def\o{\&oslash;}%
\html@def\O{\&Oslash;}%
\html@def\ss{\&szlig;}%
+\html@def\SS{\&\#7838;}%
\html@def\l{\&lstrok;}%
\html@def\L{\&Lstrok;}%
+\html@def\og{\&laquo;\&\#8239;}%
+\html@def\guillemotleft{\&laquo;\&\#8239;}%
+\html@def\fg{\&\#8239;\&raquo;}%
+\html@def\guillemotright{\&\#8239;\&raquo;}%
+\html@def\,{\&\#8239;}%
+\html@def\thinspace{\&\#8239;}%
+\html@def\textbackslash{\&\#92;}%
+\html@def\_{\&\#95;}%
+\html@def\textquestiondown{\&iquest;}%
+\html@def\textexclamdown{\&iexcl;}%
-\htmlize@record@expand{\inv}%
-\htmlize@record@expand{\rec}%
\htmlize@record@action\inlinemathrightdelim
\htmlize@record@action\displaymathrightdelim
+\def\moodle@media@find#1{%
+ \ifx\detokenize\@undefined\else
+ \edef\Gin@extensions{\detokenize\expandafter{\Gin@extensions}}%
+ \fi
+ \begingroup
+ \let\input@path\Ginput@path
+ \set@curr@file{#1}%
+ \expandafter\filename@parse\expandafter{\@curr@file}%
+ \ifx\filename@ext\Gin@gzext
+ \expandafter\filename@parse\expandafter{\filename@base}%
+ \ifx\filename@ext\relax
+ \let\filename@ext\Gin@gzext
+ \else
+ \edef\Gin@ext{\Gin@ext\Gin@sepdefault\Gin@gzext}%
+ \fi
+ \fi
+ \ifx\filename@ext\relax
+ \@for\Gin@temp:=\Gin@extensions\do{%
+ \ifx\Gin@ext\relax
+ \Gin@getbase\Gin@temp
+ \fi}%
+ \else
+ \Gin@getbase{\Gin@sepdefault\filename@ext}%
+ \ifnum0%
+ \ifx\Gin@ext\relax 1%
+ \else \@ifundefined{Gin@rule@\Gin@ext}{1}{0}%
+ \fi >0
+ \let\Gin@ext\relax
+ \let\Gin@savedbase\filename@base
+ \let\Gin@savedext\filename@ext
+ \edef\filename@base{\filename@base\Gin@sepdefault\filename@ext}%
+ \let\filename@ext\relax
+ \@for\Gin@temp:=\Gin@extensions\do{%
+ \ifx\Gin@ext\relax
+ \Gin@getbase\Gin@temp
+ \fi}%
+ \ifx\Gin@ext\relax
+ \let\filename@base\Gin@savedbase
+ \let\filename@ext\Gin@savedext
+ \fi
+ \fi
+ \ifx\Gin@ext\relax
+ \@warning{File `#1' not found}%
+ \def\Gin@base{\filename@area\filename@base}%
+ \edef\Gin@ext{\Gin@sepdefault\filename@ext}%
+ \fi
+ \fi
+ \ifx\Gin@ext\relax
+ \@latex@error{File `#1' not found}%
+ {I could not locate the file with any of these extensions:^^J%
+ \Gin@extensions^^J\@ehc}%
+ \else
+ % begin modified part
+ \xdef\moodle@media@base{\detokenize\xa{\Gin@base}}%
+ \xdef\moodle@media@ext{\detokenize\xa{\Gin@ext}}%
+ % end modfied part
+ \fi
+ \endgroup
+}
+\def\moodle@media@formats{}
+\newcommand{\DeclareMediaFormat}[3]{%
+ \xdef\moodle@media@formats{\ifx\moodle@media@formats\empty\else\moodle@media@formats,\fi#1}%
+ \csgdef{moodle@media@#1list}{#2}%
+ \csgdef{moodle@media@#1mime}{#3}%
+}%
+\DeclareMediaFormat{PNG}{.png,.PNG}{image/png}%
+\DeclareMediaFormat{JPEG}{.jpg,.JPG,.jpeg,.JPEG}{image/jpeg}%
+\DeclareMediaFormat{SVG}{.svg,.SVG}{image/svg+xml}%
+\DeclareMediaFormat{GIF}{.gif}{image/gif}%
+\DeclareMediaFormat{WAV}{.wav,.WAV}{audio/wave}%
+\DeclareMediaFormat{MP3}{.mp3,.MP3}{audio/mpeg}%
+\DeclareMediaFormat{OGG}{.ogg,.opus,.og&}{audio/ogg}%
+\DeclareMediaFormat{WEBM}{.webm,.webm}{video/webm}%
+\DeclareMediaFormat{MP4}{.mp4,.MP4,.m4v,.M4V}{video/mp4}%
+\DeclareMediaFormat{OGV}{.ogv,.OGV}{video/ogg}%
+\def\moodle@media@mime@identify#1{%
+ \edef\test@i{\detokenize\xa{#1}}%
+ \let\moodle@media@mime@current\relax
+ \edef\moodle@media@formats{\detokenize\xa{\moodle@media@formats}}%
+ \@for\@format:=\moodle@media@formats\do{%
+ \edef\@templist{\csname moodle@media@\@format list\endcsname}%
+ \@for\@ext:=\@templist\do{%
+ \ifx\moodle@media@mime@current\relax
+ \edef\@ext{\detokenize\xa{\@ext}}%
+ \ifx\test@i\@ext
+ \message{<<extension \@ext (\@format) identified>>^^J}%
+ \xdef\moodle@media@mime@current{\csname moodle@media@\@format mime\endcsname}%
+ \xdef\moodle@media@ext@current{#1}%
+ \fi
+ \fi
+ }%
+ }%
+}
\def\htmlize@setexecutable#1{%
% Defines macro #1 to be #2 in a verbatim mode suitable for filenames
\def\htmlize@executable@macro{#1}%
@@ -1918,18 +3137,55 @@
\expandafter\def\htmlize@executable@macro{#1}%
}
-\def\ghostscriptcommand{\htmlize@setexecutable\gs}
-\def\opensslcommand{\htmlize@setexecutable\openssl}
-\def\imagemagickcommand{\htmlize@setexecutable\htmlize@imagemagick@convert}
+\def\ghostscriptcommand{\htmlize@setexecutable\gs}%
+\def\baselxivcommand{\htmlize@setexecutable\baselxiv}%
+\def\imagemagickcommand{\htmlize@setexecutable\htmlize@imagemagick@convert}%
+\def\optipngcommand{\htmlize@setexecutable\optipng}%
+\def\PDFtoSVGcommand{\htmlize@setexecutable\PDFtoSVG}%
+\def\SVGtoPDFcommand{\htmlize@setexecutable\SVGtoPDF}%
+\def\optiSVGcommand{\htmlize@setexecutable\optiSVG}%
+\def\DeleteFilecommand{\htmlize@setexecutable\DeleteFiles}%
\ifwindows%
- \ghostscriptcommand{gswin64c.exe}%
+ \ghostscriptcommand{gswin64c.exe -dBATCH -dNOPAUSE -sDEVICE=pngalpha}%
+ \baselxivcommand{certutil}%
+ \DeleteFilecommand{del}%
\else%
- \ghostscriptcommand{gs}%
+ \ghostscriptcommand{gs -dBATCH -dNOPAUSE -sDEVICE=pngalpha}%
+ \baselxivcommand{base64}%
+ \DeleteFilecommand{rm -f}%
\fi%
-\opensslcommand{openssl}%
-\imagemagickcommand{convert}%
+\imagemagickcommand{convert -colorspace RGB}%
+\optipngcommand{optipng -clobber -strip all -quiet}%
+\PDFtoSVGcommand{inkscape --export-type=svg --export-area-page --vacuum-defs}%--pdf-poppler
+\SVGtoPDFcommand{inkscape --export-type=pdf --export-area-page}%
+\optiSVGcommand{scour -q --enable-id-stripping --enable-comment-stripping
+ --shorten-ids --indent=none --remove-descriptive-elements}%
+\AtEndPreamble{%
+ \@ifpackageloaded{graphicx}{%
+ \def\@firstofthree#1#2#3{#1}%
+ \def\@secondofthree#1#2#3{#2}%
+ \newcommand{\DeclareGraphicsAlien}[3]{%
+ \edef\Gin@extensions{\Gin@extensions,#1}%
+ \DeclareGraphicsRule{#1}{\@gobble#1}{#1}{}%
+ \csdef{Gread@\@gobble#1}##1{%
+ \edef\SourceFile{\Gin@base\Gin@ext}%
+ \edef\Gin@base{\Gin@base-\@gobble#1-converted-to}%
+ \edef\Gin@ext{#2}%
+ \edef\OutputFile{\Gin@base\Gin@ext}%
+ \edef\targetfmt{\expandafter\expandafter\expandafter
+ \@firstofthree\csname Gin@rule@\Gin@ext\endcsname\relax}%
+ \edef\targetext{\expandafter\expandafter\expandafter
+ \@secondofthree\csname Gin@rule@\Gin@ext\endcsname\relax}%
+ \IfFileExists{\OutputFile}{}{\ShellEscape{#3}}%
+ \csletcs{Ginclude@\@gobble#1}{Ginclude@\targetfmt}%
+ \csname Gread@\targetfmt\endcsname{\Gin@base\targetext}%
+ }%
+ }%
+ \DeclareGraphicsAlien{.gif}{.png}{\htmlize@imagemagick@convert\otherspace '\SourceFile[0]' \OutputFile}%
+ }{}%
+}%
\define@cmdkeys{moodle@includegraphics}[moodle@graphics@]{ppi}
\define@cmdkey{moodle}[moodle@graphics@]{ppi}{}% This is so the ppi key can be set at the document, quiz, or question level.
\define@cmdkeys{Gin}{ppi}% This is so the original \includegraphics will not object to a key of ppi.
@@ -1952,24 +3208,45 @@
\moodle@graphics@dimentopixels{\moodle@graphics@width@pixels}{#1}%
}
\setkeys{moodle@includegraphics}{height=0pt,width=0pt}
-\html@action@def\includegraphics{\moodle@includegraphics@int}%
- % Note that \htmlize@do@actioncs will 'patch' this by putting
- % '\xa\htmlize@proceedwiththerest\htmlize@afteraction@hook'
- % at the end. We want those 3 tokens to occur instead after
- % the graphics filename.
-\def\moodle@includegraphics@int#1#2#3{\moodle@includegraphics@int@int}%
- % This gobbles up those three spurious tokens,
- % which we will re-insert after our work is done.
-\newcommand\moodle@includegraphics@int@int[2][]{%
+\ifmoodle@svg
+ \AtEndPreamble{%
+ \DeclareGraphicsAlien{.svg}{.pdf}{%
+ \SVGtoPDF\otherspace '\SourceFile' -o '\OutputFile' 2>/dev/null}%
+ \DeclareGraphicsAlien{.SVG}{.pdf}{%
+ \SVGtoPDF\otherspace '\SourceFile' -o '\OutputFile' 2>/dev/null}%
+ }%
+\fi
+
+\ifmoodle@tikz
+\AfterEndPreamble{%
+ %\htmlize@record@expand{\embedaspict}%
+ \let\oldincludegraphics=\includegraphics
+ % patching includegraphics to trigger externalization
+ \renewcommand{\includegraphics}[2][]{%
+ %\message{moodle.sty: Processing \string\includegraphics[#1]{#2} for HTML^^J}%
+ \tikz{\node[inner sep=0pt]{\oldincludegraphics[#1]{#2}};}%
+ }%
+ % externalized images must be included with the regular command
+ \pgfkeys{/pgf/images/include external/.code={\oldincludegraphics{#1}}}%
+ \html@action@newcommand{includegraphics}[2][]{%
+ \message{moodle.sty: Processing \string\includegraphics[#1]{#2} ^^J}
+ \global\advance\numpicturesread by 1\relax
+ \edef\htmlize@imagetag{<IMG SRC="data:\TikzExportMIME;base64,\csname picbaselxiv@\the\numpicturesread\endcsname">}%
+ \xa\g@addto@macro\xa\htmlize@output\xa{\htmlize@imagetag}%
+ }%
+}%
+\else
+\html@action@newcommand{includegraphics}[2][]{%
\bgroup% The grouping is to localize the changes caused by \setkeys.
\message{moodle.sty: Processing \string\includegraphics[#1]{#2} for HTML...^^J}
\setkeys*{moodle@includegraphics}{#1}%
% Height or width should be given in TeX dimensions like cm or pt or in,
% and are converted to pixels for web use using the ppi key.
- % TO DO: Can we modify \includegraphics to accept height or width in
+ % TODO: Can we modify \includegraphics to accept height or width in
% pixels?
- % TO DO: What about \includegraphics[scale=0.7] ?
+ % TODO: What about \includegraphics[scale=0.7] ?
% Other keys: keepaspectratio=true|false, angle (rotation), clip & trim
+ % -> the package option 'tikz' offers a workaround for this
\ifnum\moodle@graphics@height@pixels=0\relax
\ifnum\moodle@graphics@width@pixels=0\relax
% No size specified. Default to height of 200 pixels.
@@ -1991,28 +3268,86 @@
\edef\moodle@graphics@htmlgeometry{width=\number\moodle@graphics@width@pixels\otherspace height=\number\moodle@graphics@height@pixels}%
\fi
\fi
- %First, convert it to PNG
- \edef\cmdline{\htmlize@imagemagick@convert\otherspace #2 -resize \moodle@graphics@geometry\otherspace #2.png}%
- \message{moodle.sty: Converting '#2' to PNG...^^J}%
- \expandafter\immediate\expandafter\write18\expandafter{\cmdline}%
- %Next, convert the PNG to base64 encoding
- \def\cmdline{\openssl\otherspace enc -base64 -in #2.png -out #2.enc}%
- \message{moodle.sty: Converting '#2.png' to base64...^^J}%
- \expandafter\immediate\expandafter\write18\expandafter{\cmdline}%
+ %Look for the file, even if no extension is provided
+ \moodle@media@find{#2}%
+ %\message{<<\moodle@media@base>>^^J}
+ %\message{<<\moodle@media@ext>>^^J}
+ %Try to identify corresponding MIME-type
+ \moodle@media@mime@identify{\moodle@media@ext}%
+ \ifx\moodle@media@mime@current\relax
+ % conversion needed
+ \edef\moodle@media@pdf{\detokenize{.pdf}}%
+ \edef\moodle@media@ext{\detokenize\xa{\moodle@media@ext}}%
+ \ifnum0\ifx\moodle@media@ext\moodle@media@pdf1\fi\ifmoodle@svg1\fi=11% PDF file and SVG option active
+ \def\moodle@media@ext@current{.svg}%
+ \edef\moodle@media@mime@current{\moodle@media@SVGmime}%
+ \edef\cmdline{\PDFtoSVG\otherspace "\moodle@media@base\moodle@media@ext" -o "\moodle@media@base\moodle@media@ext@current" 2>/dev/null}%
+ \message{moodle.sty: Converting '#2' to SVG...^^J}%
+ \xa\ShellEscape\xa{\cmdline}%
+ %Next, optimize inline
+ \ifwindows\else
+ \edef\cmdline{\optiSVG < "\moodle@media@base\moodle@media@ext@current" >
+ "\moodle@media@base.tmp.svg" && mv "\moodle@media@base.tmp.svg"
+ "\moodle@media@base\moodle@media@ext@current"}%
+ \message{moodle.sty: Optimizing '\moodle@media@base\moodle@media@ext@current'...^^J}%
+ \xa\ShellEscape\xa{\cmdline}%
+ \fi
+ \else% call ImageMagick
+ \def\moodle@media@ext@current{.png}%
+ \def\moodle@media@mime@current{image/png}%
+ \edef\cmdline{\htmlize@imagemagick@convert\otherspace "\moodle@media@base\moodle@media@ext" -resize \moodle@graphics@geometry\otherspace "\moodle@media@base\moodle@media@ext@current"}%
+ \message{moodle.sty: Converting '#2' to PNG...^^J}%
+ \xa\ShellEscape\xa{\cmdline}%
+ %Next, optimize inline
+ \edef\cmdline{\optipng\otherspace "\moodle@media@base\moodle@media@ext@current"}%
+ \message{moodle.sty: Optimizing '\moodle@media@base\moodle@media@ext@current'...^^J}%
+ \xa\ShellEscape\xa{\cmdline}%
+ \fi
+ \fi
+ %Next, convert the file to base64 encoding
+ \ConvertToBaseLXIV{\moodle@media@base}{\moodle@media@ext@current}%
%Now, save that base64 encoding in a TeX macro
\def\moodle@newpic@baselxiv{}%
- \message{moodle.sty: Reading base64 file '#2.enc'...^^J}%
- \openin\baseLXIVdatafile=#2.enc\relax
+ \message{moodle.sty: Reading base64 file '\moodle@media@base.enc'...^^J}%
+ \openin\baseLXIVdatafile="\moodle@media@base.enc"
\savebaselxivdata@recursive
\closein\baseLXIVdatafile
+ %Clean up files
+ \ifx\moodle@media@ext@current\moodle@media@ext
+ \ShellEscape{\DeleteFiles\otherspace "\moodle@media@base.enc"}%
+ \else
+ \ShellEscape{\DeleteFiles\otherspace "\moodle@media@base.enc" "\moodle@media@base\moodle@media@ext@current"}%
+ \fi
\xa\global\xa\let\csname picbaselxiv@graphics@#2\endcsname=\moodle@newpic@baselxiv%
- \edef\htmlize@imagetag{<IMG \moodle@graphics@htmlgeometry\otherspace SRC="data:image/png;base64,\csname picbaselxiv@graphics@#2\endcsname">}%
+ \edef\htmlize@imagetag{<IMG \moodle@graphics@htmlgeometry\otherspace SRC="data:\moodle@media@mime@current;base64,\csname picbaselxiv@graphics@#2\endcsname">}%
\xa\g@addto@macro\xa\htmlize@output\xa{\htmlize@imagetag}%
\message{moodle.sty: <IMG> tag inserted.^^J}%
\egroup
- % Now we re-insert the code to get the HTMLizing going again.
- \xa\htmlize@proceedwiththerest\htmlize@afteraction@hook
-}
+}%
+\fi
+\ifwindows
+ \def\ConvertToBaseLXIV#1#2{%
+ \def\cmdline{\baselxiv\otherspace -encode "#1#2"\otherspace tmp.b64 && findstr /vbc:"---" tmp.b64 > "#1" && del tmp.b64"}%
+ \message{moodle.sty: Converting '#1#2' to base64...^^J}%
+ \xa\ShellEscape\xa{\cmdline}%
+ % Starting from Windows 7, CertUtil is included by default. There should be no windows XP still running
+ }%
+\else
+ \ifmacosx
+ \def\ConvertToBaseLXIV#1#2{%
+ \def\cmdline{\baselxiv\otherspace -b 64 -i "#1#2"\otherspace -o "#1.enc"}%
+ \message{moodle.sty: Converting '#1#2' to base64...^^J}%
+ \xa\ShellEscape\xa{\cmdline}%
+ }%
+ \else % Linux, Cygwin
+ \def\ConvertToBaseLXIV#1#2{%
+ \def\cmdline{\baselxiv\otherspace "#1#2"\otherspace > "#1.enc"}%
+ \message{moodle.sty: Converting '#1#2' to base64...^^J}%
+ \xa\ShellEscape\xa{\cmdline}%
+ }%
+ % base64 is part of coreutils, add "-w 64" to get exactly the previous behavior %
+ \fi
+\fi
\newread\baseLXIVdatafile
\def\savebaselxivdata@recursive{%
\ifeof\baseLXIVdatafile
@@ -2030,31 +3365,54 @@
\fi
\baselxiv@next
}
-\newif\ifmoodle@tikzloaded
-\moodle@tikzloadedfalse
\AtBeginDocument{
\ifx\tikzpicture\@undefined
\moodle@tikzloadedfalse
\else
\moodle@tikzloadedtrue
\fi
+ \ifmoodle@draftmode
+ \long\def\tikzifexternalizing#1#2{#2}%
+ \else
\ifmoodle@tikzloaded
- \usetikzlibrary{external}
+ \usetikzlibrary{external}%
\tikzexternalize%
\tikzset{external/force remake}%
-
- \ifpdf
- \def\pdftopng{\edef\gscmdline{\gs\otherspace -dBATCH -dNOPAUSE -sDEVICE=pngalpha -sOutputFile=\tikzexternalrealjob-tikztemp-\the\numconvertedpictures.png -r200 \tikzexternalrealjob-tikztemp-\the\numconvertedpictures.pdf}%
- \expandafter\immediate\expandafter\write18\expandafter{\gscmdline}}%
+ \def\moodle@basename{\tikzexternalrealjob-tikztemp-\the\numconvertedpictures}%
+ \ifmoodle@svg
+ \def\TikzExportExtension{.svg}%
+ \def\TikzExportMIME{image/svg+xml}%
+ \ifpdfoutput% tex engines defaulting to PDF output (pdflatex, xelatex, lualatex)
+ \def\ExportTikz{ \message{moodle.sty: Converting picture '\moodle@basename.pdf' to SVG...^^J}%
+ \edef\cmdline{\PDFtoSVG\otherspace "\moodle@basename.pdf" -o "\moodle@basename\TikzExportExtension" 2>/dev/null}%
+ \xa\ShellEscape\xa{\cmdline}}%
+ \else % latex
+ \def\ExportTikz{ \message{moodle.sty: Converting picture '\moodle@basename.ps' to SVG...^^J}%
+ \edef\cmdline{\PDFtoSVG\otherspace "\moodle@basename.ps" -o "\moodle@basename\TikzExportExtension" 2>/dev/null}%
+ \xa\ShellEscape\xa{\cmdline}}%
+ \fi
+ \def\OptimizeExport{ \message{moodle.sty: Optimizing '\moodle@basename.svg'...^^J}%
+ \edef\cmdline{\optiSVG\otherspace < "\moodle@basename\TikzExportExtension" >
+ "\moodle@basename.tmp.svg" && mv "\moodle@basename.tmp.svg"
+ "\moodle@basename\TikzExportExtension" }%
+ \xa\ShellEscape\xa{\cmdline}}%
\else
- \def\pstopng{\edef\gscmdline{\gs\otherspace -dBATCH -dNOPAUSE -sDEVICE=pngalpha -sOutputFile=\tikzexternalrealjob-tikztemp-\the\numconvertedpictures.png -r200 \tikzexternalrealjob-tikztemp-\the\numconvertedpictures.ps}%
- \expandafter\immediate\expandafter\write18\expandafter{\gscmdline}}%
+ \def\TikzExportExtension{.png}%
+ \def\TikzExportMIME{image/png}%
+ \ifpdfoutput% tex engines defaulting to PDF output (pdflatex, xelatex, lualatex)
+ \def\ExportTikz{ \message{moodle.sty: Converting picture '\moodle@basename.pdf' to PNG...^^J}%
+ \edef\gscmdline{\gs\otherspace -sOutputFile=\moodle@basename\TikzExportExtension\otherspace -r150 \moodle@basename.pdf}%
+ \xa\ShellEscape\xa{\gscmdline}}%
+ \else % latex
+ \def\ExportTikz{ \message{moodle.sty: Converting picture '\moodle@basename.ps' to PNG...^^J}%
+ \edef\gscmdline{\gs\otherspace -sOutputFile=\moodle@basename\TikzExportExtension\otherspace -r150 \\moodle@basename.ps}%
+ \xa\ShellEscape\xa{\gscmdline}}%
+ \fi
+ \def\OptimizeExport{ \message{moodle.sty: Optimizing '\moodle@basename.png'...^^J}%
+ \edef\cmdline{\optipng\otherspace \moodle@basename\TikzExportExtension}%
+ \xa\ShellEscape\xa{\cmdline}}%
\fi
- \def\pngtobaselxiv{\edef\opensslcmdline{\openssl\otherspace enc -base64 -in \tikzexternalrealjob-tikztemp-\the\numconvertedpictures.png -out \tikzexternalrealjob-tikztemp-\the\numconvertedpictures.enc}%
- \expandafter\immediate\expandafter\write18\expandafter{\opensslcmdline}}%
-
\let\moodle@oldtikzpicture=\tikzpicture
-
%The following code lets us run things *before* the normal \begin{tikzpicture}.
\renewenvironment{tikzpicture}{%
\global\advance\numconvertedpictures by 1\relax
@@ -2066,43 +3424,52 @@
% However, the tikz externalize library does *not* run \end{tikzpicture}.
% In order to run commands after the tikz picture is done compiling, we need to
% use a hook into \tikzexternal@closeenvironments.
-
\g@addto@macro{\tikzexternal@closeenvironments}{%
\moodle@endtikzpicture@hook
}
\def\moodle@endtikzpicture@hook{%
\@moodle@ifgeneratexml{%
- \ifpdf
- \message{moodle.sty: Converting picture '\tikzexternalrealjob-tikztemp-\the\numconvertedpictures.pdf' to PNG...^^J}%
- \pdftopng
- \else
- \pstopng
- \fi
- \message{moodle.sty: Converting '\tikzexternalrealjob-tikztemp-\the\numconvertedpictures.png' to base64...^^J}%
- \pngtobaselxiv
+ \ExportTikz
+ \OptimizeExport
+ \ConvertToBaseLXIV{\moodle@basename}{\TikzExportExtension}%
\message{moodle.sty: Reading base64 file '\tikzexternalrealjob-tikztemp-\the\numconvertedpictures.enc'...^^J}%
\savebaselxivdata
\message{moodle.sty: base64 data saved.^^J}%
}{}%
}
- \tikzset{external/optimize=true}
- \tikzset{external/optimize command away={\VerbatimInput}{1}}
+ \ifmoodle@tikz
+ \tikzset{external/optimize=false}% due to redefinition, includegraphics must not be optimized away
+ \else
+ \tikzset{external/optimize=true}%
+ \tikzset{external/optimize command away={\VerbatimInput}{1}}%
+ \fi
%
% The HTMLizer version of the tikzpicture environment,
% which writes an <IMG> tag to the XML file.
- \htmlize@record@environment{tikzpicture}
+ \htmlize@record@environment{tikzpicture}%
\g@addto@macro\htmlize@activate@environments{%
\let\tikzpicture\relax\let\endtikzpicture\relax
\NewEnviron{tikzpicture}[1][]{%
\global\advance\numpicturesread by 1\relax
- \edef\htmlize@imagetag{<IMG SRC="data:image/png;base64,\csname picbaselxiv@\the\numpicturesread\endcsname">}%
+ \edef\htmlize@imagetag{<IMG SRC="data:\TikzExportMIME;base64,\csname picbaselxiv@\the\numpicturesread\endcsname">}%
\xa\g@addto@macro\xa\htmlize@output\xa{\htmlize@imagetag}%
}[\htmlize@patchendenvironment]%
}%
+ \html@action@newcommand{tikz}[2][]{%
+ \global\advance\numpicturesread by 1\relax
+ \edef\htmlize@imagetag{<IMG SRC="data:\TikzExportMIME;base64,\csname picbaselxiv@\the\numpicturesread\endcsname">}%
+ \xa\g@addto@macro\xa\htmlize@output\xa{\htmlize@imagetag}%
+ }%
\else
%TikZ not loaded. Provide dummy definitions for commands.
\long\def\tikzifexternalizing#1#2{#2}%
\fi
+ \fi
+ \ifmoodle@tikz
+ \tikzstyle{moodlepict}=[minimum height=1em,inner sep=0pt,execute at begin node={\begin{varwidth}{\linewidth}},execute at end node={\end{varwidth}}]
+ \newcommand\embedaspict[1]{\tikz[baseline=-\the\dimexpr\fontdimen22\textfont2\relax]{\node[moodlepict]{\mbox{#1}};}}
+ \htmlize@record@expand{\embedaspict}
+ \fi
}
\newcount\numconvertedpictures
@@ -2118,19 +3485,356 @@
\xa\global\xa\let\csname picbaselxiv@\the\numconvertedpictures\endcsname=\moodle@newpic@baselxiv%
}
-\def\@moodle@par{\par}%
-\AtEndDocument{%
+\ifmoodle@tikz
+ \ifmoodle@tikzloaded
+ \PackageWarning{moodle}{With package option 'tikz', you should not load TikZ manually.}%
+ \fi
+ \RequirePackage{tikz}%
+ \RequirePackage{varwidth}% for the command |embedaspict|
+\fi
+\AfterEndDocument{%
\ifmoodle@tikzloaded
\@moodle@ifgeneratexml{%
- \ifwindows
- \immediate\write18{del \tikzexternalrealjob-tikztemp-*.*}%
+ \ifXeTeX
+ % we must keep picture pdf's for subsequent linking (xdvipdfmx)
+ \ifwindows
+ \ShellEscape{powershell.exe -noexit "del * -include \tikzexternalrealjob-tikztemp-*.* -exclude *.pdf}%
+ \else
+ \ShellEscape{find . -type f -name "\tikzexternalrealjob-tikztemp-*.*" -not -name "*.pdf" -delete}%
+ \fi
\else
- \immediate\write18{rm \tikzexternalrealjob-tikztemp-*.*}%
+ \ShellEscape{\DeleteFiles\otherspace \tikzexternalrealjob-tikztemp-*.*}%
\fi
}{}%
\fi
}
+\AtEndPreamble{%
+ \@ifpackageloaded{hyperref}{%
+ \let\oldhref\href
+ \let\oldurl\url
+ \def\moodle@hyper@readexternallink#1#2#3#4:#5:#6\\#7{%
+ \def\filename@ext{}%
+ \def\filename@area{}%
+ \def\filename@base{}%
+ \ifx\\#6\\% if ##6 is empty (the URL contains no column -> no scheme -> local)
+ %\@hyper@linkfile file:#7\\{#3}{#2}{#7}% local file
+ %Local file (##1|##2|##3|##4|##5|##6): ##7\par
+ \filename@parse{#4}%
+ \ConvertToBaseLXIV{\filename@area\filename@base}{.\filename@ext}%
+ \else
+ \ifx\\#4\\%if ##4 is empty (no scheme was specified -> local file)
+ \filename@parse{#4}%
+ \ConvertToBaseLXIV{\filename@area\filename@base}{.\filename@ext}%
+ \else
+ \def\@pdftempa{#4}%
+ \ifx\@pdftempa\@pdftempwordfile% scheme is "file:"
+ \filename@parse{#5}%
+ \ConvertToBaseLXIV{\filename@area\filename@base}{.\filename@ext}%
+ \else
+ \ifx\@pdftempa\@pdftempwordrun% scheme is "run:"
+ \ifHy@pdfa
+ \Hy@Error{%
+ PDF/A: Launch action is prohibited%
+ }\@ehc
+ \begingroup
+ \leavevmode
+ \endgroup
+ \else% not in PDF/A mode -> run is allowed
+ %\@hyper@launch#7\\{#3}{#2}% run local file
+ \filename@parse{#5}%
+ \ConvertToBaseLXIV{\filename@area\filename@base}{.\filename@ext}%
+ \fi
+ \else% scheme is neither "file" nor "run", assuming it is a web protocol
+ %\hyper@linkurl{#3}{#7\ifx\\#2\\\else\hyper@hash#2\fi}% URL
+ \filename@parse{#7}%
+ \fi
+ \fi
+ \fi
+ \fi
+ \xdef\moodle@media@ext{.\filename@ext}%
+ \xdef\moodle@media@base{\filename@area\filename@base}%
+ }%
+ %\message{<<\moodle@media@base>>^^J}
+ %\message{<<\moodle@media@ext>>^^J}
+ %Try to identify corresponding MIME-type
+ %\edef\moodle@media@mime@current{\detokenize\xa{\moodle@media@mime@current}}%
+ }{}%
+}%
+\def\xmlDisplayVerbatimBox{border-top: thin solid; border-bottom: thin solid}%
+\html@action@def\verbatiminput#1{%
+ \message{moodle.sty: Processing \string\verbatiminput{#1} for HTML ^^J}%
+ \g@addto@macro\htmlize@output{<PRE style="\xmlDisplayVerbatimBox"><CODE>}%
+ %%%%%%%%%%%%%% from verbatim %%%%%%%%%%%%%%%%%
+ \@bsphack
+ \let\do\@makeother\dospecials
+ \catcode`\^^M\active
+ \def\verbatim@processline{\xa\g@addto@macro\xa\htmlize@output\xa{\the\verbatim@line<BR/>}}
+ \verbatim@readfile{#1}%
+ \@esphack
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ \g@addto@macro\htmlize@output{</CODE></PRE>}%
+}%
+\@ifpackageloaded{minted}{\PackageError{moodle}{'moodle' should be loaded before 'minted'.}%
+{'moodle' loads 'fancybox' which, unfortunately, redefines verbatim commands.}}{\relax}%
+\@ifpackageloaded{fvextra}{\PackageError{moodle}{'moodle' should be loaded before 'fvextra'.}%
+{'moodle' loads 'fancybox' which, unfortunately, redefines verbatim commands.}}{\relax}%
+\@ifpackageloaded{fancyvrb}{\PackageError{moodle}{'moodle' should be loaded before 'fancyvrb'.}%
+{'moodle' loads 'fancybox' which, unfortunately, redefines verbatim commands.}}{\relax}%
+
+\html@action@newcommand{VerbatimInput}[2][]{%
+ \message{moodle.sty: Processing \string\VerbatimInput[#1]{#2} for HTML ^^J}%
+ \def\FV@KeyValues{#1}%
+ \FV@UseKeyValues% import options defined in #1
+ \moodle@VerbatimInput{#2}%
+}%
+\html@action@newcommand{LVerbatimInput}[2][]{%
+ \message{moodle.sty: Processing \string\LVerbatimInput[#1]{#2} for HTML ^^J}%
+ \def\FV@KeyValues{#1}%
+ \FV@UseKeyValues% import options defined in #1
+ \moodle@VerbatimInput{#2}%
+}%
+\html@action@newcommand{BVerbatimInput}[2][]{%
+ \message{moodle.sty: Processing \string\BVerbatimInput[#1]{#2} for HTML ^^J}%
+ \def\FV@KeyValues{#1}%
+ \FV@UseKeyValues% import options defined in #1
+ \moodle@VerbatimInput{#2}%
+}%
+\def\moodle@VerbatimInput#1{%
+ \g@addto@macro\htmlize@output{<PRE style="\xmlDisplayVerbatimBox"><CODE>}%
+ %%%%%%%% using material from fancyvrb and fvextra %%%%%%%%
+ %\begingroup
+ \def\moodle@verbatim@addlinenumber##1{%
+ \g@addto@macro\htmlize@output{<span style="font-size: 80\otherpercent;
+ background-color: \otherhash f0f0f0; padding: 0 5px 0 5px; display:
+ inline-block; width: 16pt; ##1">}%
+ \if@FV@NumberBlankLines
+ \xa\g@addto@macro\xa\htmlize@output\xa{\the\c@FancyVerbLine</span>}%
+ \else
+ \ifx\FV@Line\empty
+ \xa\g@addto@macro\xa\htmlize@output\xa{\otherampersand nbsp;</span>}%
+ \else
+ \xa\g@addto@macro\xa\htmlize@output\xa{\the\c@FancyVerbLine</span>}%
+ \fi
+ \fi
+ }
+ % redefine the ProcessLine routine ('fancyvrb' and 'fvextra') for XML output
+ \def\FV@ProcessLine##1{%
+ \ifcsname FV@HighlightLine:\number\c@FancyVerbLine\endcsname
+ \xdef\moodle@FV@tagB{<mark>}% fvextra triggered highlighting for this line
+ \xdef\moodle@FV@tagE{</mark>}%
+ \else
+ \xdef\moodle@FV@tagB{}% no highlighting
+ \xdef\moodle@FV@tagE{}%
+ \fi
+ \catcode`\`=12%
+ \def\FV@Line{##1}%
+ \ifx\FV@LeftListNumber\relax
+ \else% line numbers displayed on the left side
+ \moodle@verbatim@addlinenumber{text-align: right}%
+ \fi
+ \xa\g@addto@macro\xa\htmlize@output\xa{\moodle@FV@tagB}%
+ \xa\g@addto@macro\xa\htmlize@output\xa{\FV@Line}%
+ \xa\g@addto@macro\xa\htmlize@output\xa{\moodle@FV@tagE}%
+ \ifx\FV@RightListNumber\relax\else% line numbers on the right side
+ \moodle@verbatim@addlinenumber{text-align: left; float: right}%
+ \fi
+ \g@addto@macro\htmlize@output{<BR/>}%linebreak
+ }
+ \global\FV@CodeLineNo\z@% reset codeline counter
+ \frenchspacing% Cancels special punctuation spacing.
+ \FV@DefineWhiteSpace
+ \def\FV@Space{\space}
+ \FV@DefineTabOut% replace tabs with a series a whitespaces
+ \ifdefined\FV@HighlightLinesPrep
+ \FV@HighlightLinesPrep% prepare highlighting if 'fvextra' is loaded
+ \fi
+ \FV@Input{#1}%
+ %\endgroup
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ \g@addto@macro\htmlize@output{</CODE></PRE>}%
+}%
+\AtEndPreamble{%
+ \@ifpackageloaded{fancyvrb}{%
+ % custom settings for display
+ \fvset{frame=lines,label={[Beginning of code]End of code},framesep=3mm,numbersep=9pt}%
+ }{\relax}%
+}
+\AtEndPreamble{% this definition should prevail because `minted' gets loaded after `moodle'
+\@ifpackageloaded{minted}{%
+ \newcounter{moodle@pygmentizecounter}%
+ \renewcommand{\minted@pygmentize}[2][\minted@outputdir\minted@jobname.pyg]{%
+ \minted@checkstyle{\minted@get@opt{style}{default}}%
+ \stepcounter{minted@pygmentizecounter}%
+ \ifthenelse{\equal{\minted@get@opt{autogobble}{false}}{true}}%
+ {\def\minted@codefile{\minted@outputdir\minted@jobname.pyg}}%
+ {\def\minted@codefile{#1}}%
+ \ifthenelse{\boolean{minted@isinline}}%
+ {\def\minted@optlistcl@inlines{%
+ \minted@optlistcl@g@i
+ \csname minted@optlistcl@lang\minted@lang @i\endcsname}}%
+ {\let\minted@optlistcl@inlines\@empty}%
+ \def\minted@cmdtemplate##1##2{%
+ \ifminted@kpsewhich
+ \ifwindows
+ \detokenize{for /f "usebackq tokens=*"}\space\@percentchar\detokenize{a
+ in (`kpsewhich}\space\minted@codefile\detokenize{`) do}\space
+ \fi
+ \fi
+ \MintedPygmentize\space -l #2 -f ##1 -F tokenmerge
+ \minted@optlistcl@g \csname minted@optlistcl@lang\minted@lang\endcsname
+ \minted@optlistcl@inlines
+ \minted@optlistcl@cmd -o \minted@outputdir##2\space
+ \ifminted@kpsewhich
+ \ifwindows
+ \@percentchar\detokenize{a}%
+ \else
+ \detokenize{`}kpsewhich \minted@codefile\space
+ \detokenize{||} \minted@codefile\detokenize{`}%
+ \fi
+ \else
+ \minted@codefile
+ \fi}%
+ \def\minted@cmd{\minted@cmdtemplate{latex -P commandprefix=PYG}{\minted@infile}}
+ % For debugging, uncomment: %%%%
+ \immediate\typeout{\minted@cmd}%
+ % %%%%
+ \def\minted@cmdHTML{\minted@cmdtemplate{html -P noclasses -P
+ nowrap -P hl_lines="\FV@HighlightLinesList" -P
+ style="\minted@get@opt{style}{default}"}{\csname minted@infileHTML\the\c@minted@pygmentizecounter\endcsname}}%
+ \def\minted@cmdPNG{\minted@cmdtemplate{png -P
+ line_numbers=True}{\minted@infilePNG}}%
+ \def\minted@cmdSVG{\minted@cmdtemplate{svg -P
+ linenos=True}{\minted@infileSVG}}%
+ \ifthenelse{\boolean{minted@cache}}%
+ {%
+ \ifminted@frozencache
+ \else
+ \ifx\XeTeXinterchartoks\minted@undefined
+ \ifthenelse{\equal{\minted@get@opt{autogobble}{false}}{true}}%
+ {\edef\minted@hash{\pdf@filemdfivesum{#1}%
+ \pdf@mdfivesum{\minted@cmd autogobble(\ifx\FancyVerbStartNum\z@
+ 0\else\FancyVerbStartNum\fi-\ifx\FancyVerbStopNum\z@
+ 0\else\FancyVerbStopNum\fi)}}}%
+ {\edef\minted@hash{\pdf@filemdfivesum{#1}%
+ \pdf@mdfivesum{\minted@cmd}}}%
+ \else
+ \ifx\mdfivesum\minted@undefined
+ \immediate\openout\minted@code\minted@jobname.mintedcmd\relax
+ \immediate\write\minted@code{\minted@cmd}%
+ \ifthenelse{\equal{\minted@get@opt{autogobble}{false}}{true}}%
+ {\immediate\write\minted@code{autogobble(\ifx\FancyVerbStartNum\z@
+ 0\else\FancyVerbStartNum\fi-\ifx\FancyVerbStopNum\z@
+ 0\else\FancyVerbStopNum\fi)}}{}%
+ \immediate\closeout\minted@code
+ \edef\minted@argone@esc{#1}%
+ \StrSubstitute{\minted@argone@esc}{\@backslashchar}{\@backslashchar\@backslashchar}[\minted@argone@esc]%
+ \StrSubstitute{\minted@argone@esc}{"}{\@backslashchar"}[\minted@argone@esc]%
+ \edef\minted@tmpfname@esc{\minted@outputdir\minted@jobname}%
+ \StrSubstitute{\minted@tmpfname@esc}{\@backslashchar}{\@backslashchar\@backslashchar}[\minted@tmpfname@esc]%
+ \StrSubstitute{\minted@tmpfname@esc}{"}{\@backslashchar"}[\minted@tmpfname@esc]%
+ %Cheating a little here by using ASCII codes to write `{` and `}`
+ %in the Python code
+ \def\minted@hashcmd{%
+ \detokenize{python -c "import hashlib; import os;
+ hasher = hashlib.sha1();
+ f =
+ open(os.path.expanduser(os.path.expandvars(\"}\minted@tmpfname@esc.mintedcmd\detokenize{\")),
+ \"rb\");
+ hasher.update(f.read());
+ f.close();
+ f =
+ open(os.path.expanduser(os.path.expandvars(\"}\minted@argone@esc\detokenize{\")),
+ \"rb\");
+ hasher.update(f.read());
+ f.close();
+ f =
+ open(os.path.expanduser(os.path.expandvars(\"}\minted@tmpfname@esc.mintedmd5\detokenize{\")),
+ \"w\");
+ macro = \"\\edef\\minted@hash\" + chr(123) + hasher.hexdigest()
+ + chr(125) + \"\";
+ f.write(\"\\makeatletter\" + macro +
+ \"\\makeatother\\endinput\n\");
+ f.close();"}}%
+ \ShellEscape{\minted@hashcmd}%
+ \minted@input{\minted@outputdir\minted@jobname.mintedmd5}%
+ \else
+ \ifthenelse{\equal{\minted@get@opt{autogobble}{false}}{true}}%
+ {\edef\minted@hash{\mdfivesum file {#1}%
+ \mdfivesum{\minted@cmd autogobble(\ifx\FancyVerbStartNum\z@
+ 0\else\FancyVerbStartNum\fi-\ifx\FancyVerbStopNum\z@
+ 0\else\FancyVerbStopNum\fi)}}}%
+ {\edef\minted@hash{\mdfivesum file {#1}%
+ \mdfivesum{\minted@cmd}}}%
+ \fi
+ \fi
+ \edef\minted@infile{\minted@cachedir/\minted@hash.pygtex}%
+ \edef\minted@temp@infileHTML{\minted@cachedir/\minted@hash.html}%
+ \global\cslet{minted@infileHTML\the\c@minted@pygmentizecounter}{\minted@temp@infileHTML}%
+ %\global\edef\minted@infilePNG{\minted@cachedir/\minted@hash.png}%
+ %\global\edef\minted@infileSVG{\minted@cachedir/\minted@hash.svg}%
+ \IfFileExists{\minted@infile}{}{%
+ \ifthenelse{\equal{\minted@get@opt{autogobble}{false}}{true}}{%
+ \minted@autogobble{#1}}{}%
+ \ShellEscape{\minted@cmd}%
+ \ShellEscape{\minted@cmdHTML}%
+ %\ShellEscape{\minted@cmdPNG}%
+ %\ShellEscape{\minted@cmdSVG}%
+ }%
+ \fi
+ \ifthenelse{\boolean{minted@finalizecache}}%
+ {%
+ \edef\minted@cachefilename{listing\arabic{minted@pygmentizecounter}.pygtex}%
+ \edef\minted@actualinfile{\minted@cachedir/\minted@cachefilename}%
+ \ifwindows
+ \StrSubstitute{\minted@infile}{/}{\@backslashchar}[\minted@infile@windows]
+ \StrSubstitute{\minted@actualinfile}{/}{\@backslashchar}[\minted@actualinfile@windows]
+ \ShellEscape{move /y
+ \minted@outputdir\minted@infile@windows\space\minted@outputdir\minted@actualinfile@windows}%
+ \else
+ \ShellEscape{mv -f
+ \minted@outputdir\minted@infile\space\minted@outputdir\minted@actualinfile}%
+ \fi
+ \let\minted@infile\minted@actualinfile
+ \expandafter\minted@addcachefile\expandafter{\minted@cachefilename}%
+ }%
+ {\ifthenelse{\boolean{minted@frozencache}}%
+ {%
+ \edef\minted@cachefilename{listing\arabic{minted@pygmentizecounter}.pygtex}%
+ \edef\minted@infile{\minted@cachedir/\minted@cachefilename}%
+ \expandafter\minted@addcachefile\expandafter{\minted@cachefilename}}%
+ {\expandafter\minted@addcachefile\expandafter{\minted@hash.pygtex}}%
+ }%
+ \minted@inputpyg}%
+ {%
+ \ifthenelse{\equal{\minted@get@opt{autogobble}{false}}{true}}{%
+ \minted@autogobble{#1}}{}%
+ \ShellEscape{\minted@cmd}%
+ \ShellEscape{\minted@cmdHTML}%
+ %\ShellEscape{\minted@cmdPNG}%
+ %\ShellEscape{\minted@cmdSVG}%
+ \minted@inputpyg}%
+ }%
+}{}%
+}%
+\html@action@newcommand{inputminted}[3][]{%
+ \message{moodle.sty: Processing \string\inputminted[#1]{#2}{#3} for HTML ^^J}%
+ % arguments #2 and #3 are thrown away: the job is done previously by minted when
+ % calling pygmentize. The file |\minted@infileHTML| generated with our hack will be used.
+ % Since minted is based upon `fvextra' the macro |\moodle@VerbatimInput| works here.
+ \minted@configlang{#2}% grab options set for this specific language
+ \setkeys{minted@opt@cmd}{#1}% grab options in #1
+ \minted@fvset% import options
+ \stepcounter{moodle@pygmentizecounter}
+ \xa\moodle@VerbatimInput\xa{\csname minted@infileHTML\the\c@moodle@pygmentizecounter\endcsname}%
+}%
+\AtBeginDocument{%
+ \ifPDFTeX % pdflatex or latex
+ \@ifpackagewith{babel}{french}{%
+ \PackageWarning{moodle}{Be careful when using LaTeX, moodle, and the babel package with option 'french'. Autospacing produces in undesired symbols in the XML. You can either 1) compile with xelatex/lualatex or 2) add '\NoAutoSpacing' after '\begin{quiz}'.}%
+ }{\relax}%
+ \fi
+}%
\endinput
%%
%% End of file `moodle.sty'.