From d52d5933119ff87b3054cdd6a14d3dfb66b30001 Mon Sep 17 00:00:00 2001 From: Alex Jordan Date: Tue, 11 Jul 2023 13:51:19 -0700 Subject: [PATCH 01/15] refactor hardcopy themes --- .gitignore | 1 - assets/hardcopyThemes/README.md | 98 ++++++++++ assets/hardcopyThemes/basic.xml | 63 ++++++ assets/hardcopyThemes/basicTwoCol.xml | 68 +++++++ assets/hardcopyThemes/boxed.xml | 71 +++++++ assets/hardcopyThemes/boxedRows.xml | 66 +++++++ assets/hardcopyThemes/boxedTwoCol.xml | 77 ++++++++ assets/hardcopyThemes/classic.xml | 66 +++++++ assets/hardcopyThemes/classicTwoCol.xml | 70 +++++++ assets/hardcopyThemes/empty.xml | 44 +++++ assets/hardcopyThemes/hebrew.xml | 91 +++++++++ assets/hardcopyThemes/hebrewTwoCol.xml | 100 ++++++++++ assets/hardcopyThemes/oneColumn.xml | 68 +++++++ assets/hardcopyThemes/twoColumn.xml | 73 +++++++ {conf/snippets => assets/pg}/blankProblem.pg | 0 {conf/snippets => assets/pg}/blankProblem2.pg | 0 .../pg}/defaultSetHeader.pg | 2 - {conf/snippets => assets/pg}/newProblem.pg | 0 .../common => assets/tex}/webwork2.sty | 54 +++++- .../common => assets/tex}/webwork_logo.png | Bin bin/check_latex | 9 +- bin/check_latex_article.tex | 44 +++++ bin/{check_latex.tex => check_latex_exam.tex} | 11 +- bin/check_modules.pl | 1 + conf/defaults.config | 150 +++++++-------- conf/localOverrides.conf.dist | 69 +++---- conf/snippets/hardcopyPostamble.tex | 1 - conf/snippets/hardcopyPreamble.tex | 1 - conf/snippets/hardcopyProblemDivider.tex | 1 - conf/snippets/hardcopySetDivider.tex | 1 - conf/snippets/hardcopySetFooter.tex | 1 - conf/snippets/hardcopySetHeader.tex | 1 - .../hardcopyPostamble.tex | 3 - .../hardcopyPreamble.tex | 57 ------ .../hardcopyProblemDivider.tex | 6 - .../hardcopySetDivider.tex | 4 - .../hardcopySetFooter.tex | 1 - .../hardcopySetHeader.pg | 1 - .../hardcopySetHeader.tex | 0 .../hardcopyUserDivider.tex | 3 - .../hardcopyPostamble.tex | 3 - .../hardcopyPreamble.tex | 61 ------ .../hardcopyProblemDivider.tex | 6 - .../hardcopySetDivider.tex | 4 - .../hardcopySetFooter.tex | 2 - .../hardcopySetHeader.pg | 1 - .../hardcopySetHeader.tex | 1 - .../hardcopyUserDivider.tex | 3 - .../XeLaTeX-oneColumn/hardcopyPostamble.tex | 3 - .../XeLaTeX-oneColumn/hardcopyPreamble.tex | 51 ----- .../hardcopyProblemDivider.tex | 6 - .../XeLaTeX-oneColumn/hardcopySetDivider.tex | 3 - .../XeLaTeX-oneColumn/hardcopySetFooter.tex | 1 - .../XeLaTeX-oneColumn/hardcopySetHeader.pg | 1 - .../XeLaTeX-oneColumn/hardcopySetHeader.tex | 0 .../XeLaTeX-oneColumn/hardcopyUserDivider.tex | 3 - .../XeLaTeX-twoColumn/hardcopyPostamble.tex | 3 - .../XeLaTeX-twoColumn/hardcopyPreamble.tex | 54 ------ .../hardcopyProblemDivider.tex | 6 - .../XeLaTeX-twoColumn/hardcopySetDivider.tex | 4 - .../XeLaTeX-twoColumn/hardcopySetFooter.tex | 2 - .../XeLaTeX-twoColumn/hardcopySetHeader.pg | 1 - .../XeLaTeX-twoColumn/hardcopySetHeader.tex | 1 - .../XeLaTeX-twoColumn/hardcopyUserDivider.tex | 3 - conf/snippets/hardcopyThemes/common/CAPA.tex | 15 -- conf/snippets/hardcopyThemes/common/PGML.tex | 71 ------- .../hardcopyThemes/common/copyright.tex | 1 - .../hardcopyThemes/common/packages.tex | 32 ---- .../oneColumn/hardcopyPostamble.tex | 3 - .../oneColumn/hardcopyPreamble.tex | 23 --- .../oneColumn/hardcopyProblemDivider.tex | 6 - .../oneColumn/hardcopySetDivider.tex | 3 - .../oneColumn/hardcopySetFooter.tex | 1 - .../oneColumn/hardcopySetHeader.tex | 0 .../oneColumn/hardcopyUserDivider.tex | 3 - .../twoColumn/hardcopyPostamble.tex | 3 - .../twoColumn/hardcopyPreamble.tex | 25 --- .../twoColumn/hardcopyProblemDivider.tex | 6 - .../twoColumn/hardcopySetDivider.tex | 3 - .../twoColumn/hardcopySetFooter.tex | 2 - .../twoColumn/hardcopySetHeader.tex | 1 - .../twoColumn/hardcopyUserDivider.tex | 3 - conf/snippets/hardcopyUserDivider.tex | 1 - lib/HardcopyRenderedProblem.pm | 56 +++--- lib/WeBWorK/ConfigObject/checkboxlist.pm | 2 +- lib/WeBWorK/ContentGenerator/Hardcopy.pm | 179 ++++++++++-------- .../ContentGenerator/Instructor/Config.pm | 25 ++- .../Instructor/PGProblemEditor.pm | 20 +- .../ContentGenerator/Hardcopy/form.html.ep | 33 +++- .../PGProblemEditor/hardcopy_form.html.ep | 6 +- templates/HelpFiles/Hardcopy.html.ep | 2 +- 91 files changed, 1364 insertions(+), 761 deletions(-) create mode 100644 assets/hardcopyThemes/README.md create mode 100644 assets/hardcopyThemes/basic.xml create mode 100644 assets/hardcopyThemes/basicTwoCol.xml create mode 100644 assets/hardcopyThemes/boxed.xml create mode 100644 assets/hardcopyThemes/boxedRows.xml create mode 100644 assets/hardcopyThemes/boxedTwoCol.xml create mode 100644 assets/hardcopyThemes/classic.xml create mode 100644 assets/hardcopyThemes/classicTwoCol.xml create mode 100644 assets/hardcopyThemes/empty.xml create mode 100644 assets/hardcopyThemes/hebrew.xml create mode 100644 assets/hardcopyThemes/hebrewTwoCol.xml create mode 100644 assets/hardcopyThemes/oneColumn.xml create mode 100644 assets/hardcopyThemes/twoColumn.xml rename {conf/snippets => assets/pg}/blankProblem.pg (100%) rename {conf/snippets => assets/pg}/blankProblem2.pg (100%) rename {conf/snippets => assets/pg}/defaultSetHeader.pg (99%) rename {conf/snippets => assets/pg}/newProblem.pg (100%) rename {conf/snippets/hardcopyThemes/common => assets/tex}/webwork2.sty (51%) rename {conf/snippets/hardcopyThemes/common => assets/tex}/webwork_logo.png (100%) create mode 100644 bin/check_latex_article.tex rename bin/{check_latex.tex => check_latex_exam.tex} (93%) delete mode 120000 conf/snippets/hardcopyPostamble.tex delete mode 120000 conf/snippets/hardcopyPreamble.tex delete mode 120000 conf/snippets/hardcopyProblemDivider.tex delete mode 120000 conf/snippets/hardcopySetDivider.tex delete mode 120000 conf/snippets/hardcopySetFooter.tex delete mode 120000 conf/snippets/hardcopySetHeader.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopyPostamble.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopyPreamble.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopyProblemDivider.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopySetDivider.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopySetFooter.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopySetHeader.pg delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopySetHeader.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopyUserDivider.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopyPostamble.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopyPreamble.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopyProblemDivider.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopySetDivider.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopySetFooter.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopySetHeader.pg delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopySetHeader.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopyUserDivider.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopyPostamble.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopyPreamble.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopyProblemDivider.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopySetDivider.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopySetFooter.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopySetHeader.pg delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopySetHeader.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopyUserDivider.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopyPostamble.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopyPreamble.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopyProblemDivider.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopySetDivider.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopySetFooter.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopySetHeader.pg delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopySetHeader.tex delete mode 100644 conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopyUserDivider.tex delete mode 100644 conf/snippets/hardcopyThemes/common/CAPA.tex delete mode 100644 conf/snippets/hardcopyThemes/common/PGML.tex delete mode 100644 conf/snippets/hardcopyThemes/common/copyright.tex delete mode 100644 conf/snippets/hardcopyThemes/common/packages.tex delete mode 100644 conf/snippets/hardcopyThemes/oneColumn/hardcopyPostamble.tex delete mode 100644 conf/snippets/hardcopyThemes/oneColumn/hardcopyPreamble.tex delete mode 100644 conf/snippets/hardcopyThemes/oneColumn/hardcopyProblemDivider.tex delete mode 100644 conf/snippets/hardcopyThemes/oneColumn/hardcopySetDivider.tex delete mode 100644 conf/snippets/hardcopyThemes/oneColumn/hardcopySetFooter.tex delete mode 100644 conf/snippets/hardcopyThemes/oneColumn/hardcopySetHeader.tex delete mode 100644 conf/snippets/hardcopyThemes/oneColumn/hardcopyUserDivider.tex delete mode 100644 conf/snippets/hardcopyThemes/twoColumn/hardcopyPostamble.tex delete mode 100644 conf/snippets/hardcopyThemes/twoColumn/hardcopyPreamble.tex delete mode 100644 conf/snippets/hardcopyThemes/twoColumn/hardcopyProblemDivider.tex delete mode 100644 conf/snippets/hardcopyThemes/twoColumn/hardcopySetDivider.tex delete mode 100644 conf/snippets/hardcopyThemes/twoColumn/hardcopySetFooter.tex delete mode 100644 conf/snippets/hardcopyThemes/twoColumn/hardcopySetHeader.tex delete mode 100644 conf/snippets/hardcopyThemes/twoColumn/hardcopyUserDivider.tex delete mode 120000 conf/snippets/hardcopyUserDivider.tex diff --git a/.gitignore b/.gitignore index bba43a6b02..f02c53bd36 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,6 @@ logs/* conf/* !conf/*.dist* !conf/*.config -!conf/snippets node_modules diff --git a/assets/hardcopyThemes/README.md b/assets/hardcopyThemes/README.md new file mode 100644 index 0000000000..04860a2a82 --- /dev/null +++ b/assets/hardcopyThemes/README.md @@ -0,0 +1,98 @@ +# Hardcopy Themes + +A hardcopy theme is an XML file with root ``. The `` element has an attirubute `label` that is used to +define a label for the theme, for example, `label="Empty"`. It has children: + +* `` +* `` +* `` +* `` +* `` +* `` +* `` +* `` +* `` +* `` +* `` + +The `` element contains a simple text description of the theme. All other elements contain text snippets +that will be inserted into a `.tex` file. + +The `` and `` wrap the file. Note that `webwork2` will write `\batchmode` to the `.tex` file even +before `` is written. The `` must include `\usepackage{webwork2}` to load `webwork2.sty` for many +things to work. + +Next `webwork2` will loop through users (often just one) and loop through problem sets (often just one) and write TeX +for all combinations. `` and `` are snippets of TeX that are inserted when transitioning to a +new user or a new set. Typically these should just start a new page and reset page numbering. + +When an individual user-set is being processed, first the `` snippet will be used. Then the PG header +file will be processed. Then the `` snippet will be used. At the end of the set `webwork2` attempts to +make the last page display a copyright claim. Then the `` snippet is used. + +Each problem is wrapped in `` and ``, and `` is used between adjacent +problems. + +## Packages + +A theme preamble can load packages, but as soon as it loads `webwork2`, it is already loading `path`, `listings`, +`hyperref`, and `ifthen`. So you can use tools from these packages without loading them in your theme. + +Also `webwork2` loads `pg.sty` from the `pg` distribution. This loads `amsmath`, `amsfonts`, `amssymb`, `booktabs`, +`tabularx`, `colortbl`, `caption`, `xcolor`, `mhchem`, and `graphicx`. So again you can use tools from these packages +without loading them in your theme. + +## Macros + +The following macros are provided by the `webwork2` package. They may be empty, but `webwork2` should populate them +with appropriate values as the `.tex` file is built. So you can use these when building your theme. + +* `\webworkCourseName` +* `\webworkCourseTitle` +* `\webworkCourseURL` +* `\webworkUserId` (the user's username) +* `\webworkStudentId` (the user's Student ID) +* `\webworkFirstName` +* `\webworkLastName` +* `\webworkEmailAddress` +* `\webworkSection` +* `\webworkRecitation` +* `\webworkSetId` (the actual name of the set which may have underscores) +* `\webworkPrettySetId` (a version where underscores have been converted to spaces) +* `\webworkDescription` +* `\webworkOpenDate` +* `\webworkReducedScoringDate` +* `\webworkDueDate` +* `\webworkAnswerDate` +* `\webworkProblemNumber` (the number of the problem in the set) +* `\webworkProblemId` (may differ from the problem number for a versioned test with randomized order) +* `\webworkProblemWeight` +* `\webworkAssignmentCourseInfo` (a multiline expression with the set name, dates, and course name) +* `\webworkUserInfo` (a multiline expression with the user's name, ID, section, and recitation) +* `webworkPageNumber` (this just displays the page number, preceded by "Page" which can be localized) + +Words and phrases might be localized automatically by `webwork2` in the future, but a theme can override these. + +* `\webworkLocalizeAssignment` +* `\webworkLocalizeSet` +* `\webworkLocalizeProblem` +* `\webworkLocalizeUsername` +* `\webworkLocalizeFullCreditBy` +* `\webworkLocalizeCloses` +* `\webworkLocalizeSection` +* `\webworkLocalizeRecitation` +* `\webworkLocalizePage` +* `\webworkLocalizePoint` + +## Config + +Theme files belong in `webwork2/assets/hardcopyThemes` or in a course's `templates/hardcopyThemes` folder. Both of +these paths can be configured in `localOverrides.conf`, following the initialization in `defaults.config`. If a theme +in `templates/hardcopyThemes` has the same filename as a theme in `webwork2/assets/hardcopyThemes`, the one from +`templates/hardcopyThemes` will be used. + +A course will "see" all the theme files in these locations and make them available to be enabled in Course Config. +Only the enabled themes will be offered for use when producing a hardcopy. + +In addition to enabling themes in Course Config, you can also set the default hardcopy theme for regular hardcopy +production, and separately set a default hardcopy theme for use by the PG Editor. diff --git a/assets/hardcopyThemes/basic.xml b/assets/hardcopyThemes/basic.xml new file mode 100644 index 0000000000..d42f44bb9b --- /dev/null +++ b/assets/hardcopyThemes/basic.xml @@ -0,0 +1,63 @@ + + + + +This theme produces hardcopies with minimal page headers displaying the set +title and useername, and minimal problem numbering. + + + +\documentclass{article} +\usepackage{webwork2} +\usepackage[text={6in,9in},centering]{geometry} +\usepackage{fancyhdr} +\parindent=0pt +\pagestyle{fancy} +\begin{document} + + + +\fancyhead{} +\renewcommand{\headrulewidth}{0pt} +\ifthenelse{\equal{\webworkPrettySetId}{}}{}{\fancyhead[L]{\ifthenelse{\thepage=1}{\large\scshape\webworkLocalizeSet: \webworkPrettySetId}{}}} +\ifthenelse{\equal{\webworkUserId}{}}{}{\fancyhead[R]{\ifthenelse{\thepage=1}{\bfseries\webworkLocalizeUsername: \webworkUserId}{}}} +\fancyfoot{} +\fancyfoot[C]{\webworkPageNumber} + + + +\bigskip + + + +{\bfseries\webworkLocalizeProblem~\ifx\webworkProblemNumber\empty{1}\else{\webworkProblemNumber}\fi} +\ifx\webworkProblemWeight\empty\else{(\webworkProblemWeight~\webworkLocalizePoint)}\fi +\nobreak +\smallskip + + + + + +\vspace{2pc+6pc-1pc} +\goodbreak + + + + + + +\newpage +\setcounter{page}{1} + + + +\newpage +\setcounter{page}{1} + + + +\end{document} + + + diff --git a/assets/hardcopyThemes/basicTwoCol.xml b/assets/hardcopyThemes/basicTwoCol.xml new file mode 100644 index 0000000000..0972430da8 --- /dev/null +++ b/assets/hardcopyThemes/basicTwoCol.xml @@ -0,0 +1,68 @@ + + + + +This theme produces hardcopies with minimal page headers displaying the set +title and useername, and minimal problem numbering. With two columns. + + + +\documentclass{article} +\usepackage{webwork2} +\usepackage[text={6in,9in},centering]{geometry} +\usepackage{multicol} +\setlength{\columnsep}{.25in} +\setlength{\columnseprule}{.4pt} +\usepackage{fancyhdr} +\parindent=0pt +\pagestyle{fancy} +\begin{document} + + + +\fancyhead{} +\renewcommand{\headrulewidth}{0pt} +\ifthenelse{\equal{\webworkPrettySetId}{}}{}{\fancyhead[L]{\ifthenelse{\thepage=1}{\large\scshape\webworkLocalizeSet: \webworkPrettySetId}{}}} +\ifthenelse{\equal{\webworkUserId}{}}{}{\fancyhead[R]{\ifthenelse{\thepage=1}{\bfseries\webworkLocalizeUsername: \webworkUserId}{}}} +\fancyfoot{} +\fancyfoot[C]{\webworkPageNumber} + + + +\bigskip +\begin{multicols*}{2} + + + +{\bfseries\webworkLocalizeProblem~\ifx\webworkProblemNumber\empty{1}\else{\webworkProblemNumber}\fi} +\ifx\webworkProblemWeight\empty\else{(\webworkProblemWeight~\webworkLocalizePoint)}\fi +\nobreak +\smallskip + + + + + +\vspace{2pc+6pc-1pc} +\goodbreak + + + +\end{multicols*} + + + +\newpage +\setcounter{page}{1} + + + +\newpage +\setcounter{page}{1} + + + +\end{document} + + + diff --git a/assets/hardcopyThemes/boxed.xml b/assets/hardcopyThemes/boxed.xml new file mode 100644 index 0000000000..3a97fe498d --- /dev/null +++ b/assets/hardcopyThemes/boxed.xml @@ -0,0 +1,71 @@ + + + + +This theme uses the tcolorbox package to put each exercisee in a box. + + + +\documentclass[11pt]{article} +\usepackage{webwork2} +\usepackage[text={7in,9in},centering]{geometry} +\usepackage{tcolorbox} +\tcbuselibrary{breakable, skins} +\newtcolorbox{webworkexercise}[2]{ + breakable, + enhanced jigsaw, + title={ + {\bfseries\webworkLocalizeProblem~\ifthenelse{\equal{#1}{}}{}{~#1}}\hfill + \ifthenelse{\equal{#2}{}}{}{(#2~\webworkLocalizePoint)} + } +} +\usepackage{fancyhdr} +\parindent=0pt +\setlength{\parskip}{1pc} +\pagestyle{fancy} +\begin{document} + + + +\fancyhead{} +\renewcommand{\headrulewidth}{0pt} +\ifthenelse{\equal{\webworkPrettySetId}{}}{}{\fancyhead[L]{\ifthenelse{\thepage=1}{\webworkAssignmentCourseInfo}{}}} +\ifthenelse{\equal{\webworkUserId}{}}{}{\fancyhead[R]{\ifthenelse{\thepage=1}{\webworkUserInfo}{}}} +\fancyfoot{} +\fancyfoot[C]{\webworkPageNumber} + + + +\medskip + + +% +\begin{webworkexercise}{\webworkProblemNumber}{\webworkProblemWeight}% + + +% +\end{webworkexercise}% + + + +\smallskip +\goodbreak + + + + + +\newpage% +\setcounter{page}{1}% + + + +\newpage% +\setcounter{page}{1}% + + + +\end{document} + + + diff --git a/assets/hardcopyThemes/boxedRows.xml b/assets/hardcopyThemes/boxedRows.xml new file mode 100644 index 0000000000..16c8305938 --- /dev/null +++ b/assets/hardcopyThemes/boxedRows.xml @@ -0,0 +1,66 @@ + + + + +This theme uses the tcolorbox package to put each exercisee in a box. +Exercises progress row-major instead of the usual column-major, in two columns. +Exerecises in this theme will not break across pages, so this theme is better +suited for sets with short exercises. + + + +\documentclass[10pt]{article} +\usepackage{webwork2} +\usepackage[text={7.5in,9in},centering]{geometry} +\usepackage{tcolorbox} +\tcbuselibrary{raster} +\newtcolorbox{webworkexercise}[2]{ + title={ + {\bfseries\webworkLocalizeProblem~\ifthenelse{\equal{#1}{}}{}{~#1}}\hfill + \ifthenelse{\equal{#2}{}}{}{(#2~\webworkLocalizePoint)} + }, +} + +\usepackage{fancyhdr} +\parindent=0pt +\setlength{\parskip}{1pc} +\pagestyle{fancy} +\begin{document} + + + +\fancyhead{} +\ifthenelse{\equal{\webworkPrettySetId}{}}{}{\fancyhead[L]{\ifthenelse{\thepage=1}{\webworkAssignmentCourseInfo}{}}} +\ifthenelse{\equal{\webworkUserId}{}}{}{\fancyhead[R]{\ifthenelse{\thepage=1}{\webworkUserInfo}{}}} +\fancyfoot{} +\fancyfoot[C]{\webworkPageNumber} + + + +\bigskip +\begin{tcbraster}[raster columns=2, raster valign=top] + + +\begin{webworkexercise}{\webworkProblemNumber}{\webworkProblemWeight}% + +\end{webworkexercise} + + + +\end{tcbraster} + + +\newpage% +\setcounter{page}{1}% + + + +\newpage% +\setcounter{page}{1}% + + + +\end{document} + + + diff --git a/assets/hardcopyThemes/boxedTwoCol.xml b/assets/hardcopyThemes/boxedTwoCol.xml new file mode 100644 index 0000000000..b6be04e9ad --- /dev/null +++ b/assets/hardcopyThemes/boxedTwoCol.xml @@ -0,0 +1,77 @@ + + + + +This theme uses the tcolorbox package to put each exercisee in a box. +With two columns. + + + +\documentclass[10pt]{article} +\usepackage{webwork2} +\usepackage[text={7in,9in},centering]{geometry} +\usepackage{tcolorbox} +\tcbuselibrary{breakable, skins} +\newtcolorbox{webworkexercise}[2]{ + breakable, + enhanced jigsaw, + title={ + {\bfseries\webworkLocalizeProblem~\ifthenelse{\equal{#1}{}}{}{~#1}}\hfill + \ifthenelse{\equal{#2}{}}{}{(#2~\webworkLocalizePoint)} + } +} +\usepackage{multicol} +\setlength{\columnsep}{.2in} +\usepackage{fancyhdr} +\parindent=0pt +\setlength{\parskip}{1pc} +\pagestyle{fancy} +\begin{document} + + + +\fancyhead{} +\renewcommand{\headrulewidth}{0pt} +\ifthenelse{\equal{\webworkPrettySetId}{}}{}{\fancyhead[L]{\ifthenelse{\thepage=1}{\webworkAssignmentCourseInfo}{}}} +\ifthenelse{\equal{\webworkUserId}{}}{}{\fancyhead[R]{\ifthenelse{\thepage=1}{\webworkUserInfo}{}}} +\fancyfoot{} +\fancyfoot[C]{\webworkPageNumber} + + + +\medskip +\begin{multicols*}{2} + + +% +\begin{webworkexercise}{\webworkProblemNumber}{\webworkProblemWeight}% + + +% +\end{webworkexercise}% + + + +\smallskip +\goodbreak + + + +\end{multicols*} + + + +\newpage% +\setcounter{page}{1}% + + + +\newpage% +\setcounter{page}{1}% + + + +\end{document} + + + diff --git a/assets/hardcopyThemes/classic.xml b/assets/hardcopyThemes/classic.xml new file mode 100644 index 0000000000..e3d73b4d29 --- /dev/null +++ b/assets/hardcopyThemes/classic.xml @@ -0,0 +1,66 @@ + + + + +This theme produces hardcopies styled as hardcopies were prior to version 2.18. + + + +\documentclass[11pt]{amsart} +\usepackage{webwork2} +\usepackage{pslatex} +\usepackage{fullpage} +\parindent=0pt +\begin{document} + + + +\noindent {\large \bfseries \webworkFirstName\ \webworkLastName} +\hfill +{\large \bfseries \webworkCourseName} +\par +\ifx\webworkSetId\empty\else\noindent{\large \bfseries {\webworkLocalizeAssignment\ \webworkSetId\ due \webworkDueDate}}\fi + + + +\medskip\hrule\nobreak\smallskip + + + +{\bfseries\webworkLocalizeProblem~\ifx\webworkProblemNumber\empty{1}\else{\webworkProblemNumber}\fi.} +\ifx\webworkProblemWeight\empty\else{\bfseries\footnotesize(\webworkProblemWeight~\webworkLocalizePoint)}\fi +\nobreak +\smallskip + + + + + +\vfill +\goodbreak +\hrule +\nobreak +\smallskip + + + +\nobreak\noindent {\tiny Generated by \copyright WeBWorK, https://openwebwork.org, The~WeBWorK~Project} + + + +\newpage% +\setcounter{page}{1}% + + + +\newpage% +\setcounter{page}{1}% + + + + +\vfill +\end{document} + + + diff --git a/assets/hardcopyThemes/classicTwoCol.xml b/assets/hardcopyThemes/classicTwoCol.xml new file mode 100644 index 0000000000..b07e6d0843 --- /dev/null +++ b/assets/hardcopyThemes/classicTwoCol.xml @@ -0,0 +1,70 @@ + + + + +This theme produces hardcopies styled as hardcopies were prior to version 2.18. + + + +\documentclass[11pt]{amsart} +\usepackage{webwork2} +\usepackage{pslatex} +\usepackage{fullpage} +\usepackage{multicol} +\setlength{\columnsep}{.25in} +\setlength{\columnseprule}{.4pt} +\parindent=0pt +\begin{document} + + + +\noindent {\large \bfseries \webworkFirstName\ \webworkLastName} +\hfill +{\large \bfseries \webworkCourseName} +\par +\ifx\webworkSetId\empty\else\noindent{\large \bfseries {\webworkLocalizeAssignment\ \webworkSetId\ due \webworkDueDate}}\fi + + + +\medskip\hrule\nobreak\smallskip +\begin{multicols}{2}\raggedcolumns + + + +{\bfseries\webworkLocalizeProblem~\ifx\webworkProblemNumber\empty{1}\else{\webworkProblemNumber}\fi.} +\ifx\webworkProblemWeight\empty\else{\bfseries\footnotesize(\webworkProblemWeight~\webworkLocalizePoint)}\fi +\nobreak +\smallskip + + + + + +\vfill +\goodbreak +\hrule +\nobreak +\smallskip + + + +\end{multicols}\nobreak\noindent {\tiny Generated by \copyright WeBWorK, https://openwebwork.org, The~WeBWorK~Project} + + + +\newpage% +\setcounter{page}{1}% + + + +\newpage% +\setcounter{page}{1}% + + + + +\vfill +\end{document} + + + diff --git a/assets/hardcopyThemes/empty.xml b/assets/hardcopyThemes/empty.xml new file mode 100644 index 0000000000..0803c17bec --- /dev/null +++ b/assets/hardcopyThemes/empty.xml @@ -0,0 +1,44 @@ + + + + +This theme is meant for rendering problems with no metadata or styling beyond +the LaTeX defaults for the article class. Each problem gets its own page, +including the PG header. + + + +\documentclass{article} +\usepackage{webwork2} +\pagestyle{empty} +\parindent=0pt +\begin{document} + + + + + + + +\newpage + + + + + + + + + +\newpage + + + +\newpage + + + +\end{document} + + + diff --git a/assets/hardcopyThemes/hebrew.xml b/assets/hardcopyThemes/hebrew.xml new file mode 100644 index 0000000000..6b6c7803ea --- /dev/null +++ b/assets/hardcopyThemes/hebrew.xml @@ -0,0 +1,91 @@ + + + + +This theme is like "One Column" but with the necessary components to include +Hebrew script. This theme should only be used if xelatex is the latex engine. + + + +\documentclass[11pt]{exam} +\usepackage{webwork2} +\usepackage[text={7.5in,9in},centering]{geometry} + +% bidi needs to be loaded AFTER caption, xcolor, and geometry. +\usepackage{bidi} + +\setdefaultlanguage{hebrew} +\setotherlanguage{english} +\setmainfont{Frank Ruehl CLM} +\setmonofont{Miriam Mono CLM} +\setsansfont{Simple CLM} + +% When using default English +% Use \begin{hebrew} block of text \end{hebrew} for paragraphs. +% +% When using default Hebrew +% Use \begin{hebrew} block of text \end{hebrew} for paragraphs. + +% This removes the margin for questions from the exam class. +\renewcommand{\questionshook}{\leftmargin=0pt\labelwidth=-\labelsep} +\makeatletter +\qformat{{\bfseries \webworkLocalizeProblem~\thequestiontitle.} \if@placepoints{\bfseries\footnotesize(\thepoints)}\fi \hfill} +\makeatother +\parindent=0pt +\pagestyle{headandfoot} +\begin{document} + + + +\def\webworkLocalizeProblem{שאלה} +% This needs a Hebrew localizations for +\def\webworkLocalizeAssignment{Assignment} +\def\webworkLocalizeFullCreditBy{full credit by} +\def\webworkLocalizeCloses{closes} +\def\webworkLocalizeSection{Section} +\def\webworkLocalizeRecitation{Recitation} +\def\webworkLocalizePage{Page} +\firstpageheader{\webworkAssignmentCourseInfo}{}{\webworkUserInfo} +\runningheader{}{}{} +\footer{}{\webworkPageNumber}{} + + + +\smallskip +\hrule +\begin{questions} + + + +\ifthenelse{\equal{\webworkProblemNumber}{}}{\question}{\titledquestion{\webworkProblemNumber}[\webworkProblemWeight]} + + + + + +\vfill +\goodbreak +\hrule +\nobreak +\smallskip + + + +\end{questions} + + + +\newpage% +\setcounter{page}{1}% + + + +\newpage% +\setcounter{page}{1}% + + + +\end{document} + + + diff --git a/assets/hardcopyThemes/hebrewTwoCol.xml b/assets/hardcopyThemes/hebrewTwoCol.xml new file mode 100644 index 0000000000..e3c1abb79b --- /dev/null +++ b/assets/hardcopyThemes/hebrewTwoCol.xml @@ -0,0 +1,100 @@ + + + + +This theme is like "Two Column" but with the necessary components to include +Hebrew script. This theme should only be used if xelatex is the latex engine. + + + + +\documentclass[11pt]{exam} +\usepackage{webwork2} +\usepackage[text={7.5in,9in},centering]{geometry} +\usepackage{multicol} +\setlength{\columnsep}{.25in} +\setlength{\columnseprule}{.4pt} + +% bidi needs to be loaded AFTER caption, xcolor, and geometry. +\usepackage{bidi} + +\setdefaultlanguage{hebrew} +\setotherlanguage{english} +\setmainfont{Frank Ruehl CLM} +\setmonofont{Miriam Mono CLM} +\setsansfont{Simple CLM} + +% When using default English +% Use \begin{hebrew} block of text \end{hebrew} for paragraphs. +% +% When using default Hebrew +% Use \begin{hebrew} block of text \end{hebrew} for paragraphs. + +% This removes the margin for questions from the exam class. +\renewcommand{\questionshook}{\leftmargin=0pt\labelwidth=-\labelsep} +\makeatletter +\qformat{{\bfseries \webworkLocalizeProblem~\thequestiontitle.} \if@placepoints{\bfseries\footnotesize(\thepoints)}\fi \hfill} +\makeatother +\parindent=0pt +\pagestyle{headandfoot} +\begin{document} + + + +\def\webworkLocalizeProblem{שאלה} +% This needs a Hebrew localizations for +\def\webworkLocalizeAssignment{Assignment} +\def\webworkLocalizeFullCreditBy{full credit by} +\def\webworkLocalizeCloses{closes} +\def\webworkLocalizeSection{Section} +\def\webworkLocalizeRecitation{Recitation} +\def\webworkLocalizePage{Page} +\firstpageheader{\webworkAssignmentCourseInfo}{}{\webworkUserInfo} +\runningheader{}{}{} +\footer{}{\webworkPageNumber}{} + + + +\smallskip +\hrule +\begin{multicols*}{2} +\begin{questions} + + + +\ifthenelse{\equal{\webworkProblemId}{}\OR\equal{\webworkProblemId}{1}}{}{\hrule} +\nobreak +\smallskip +\ifthenelse{\equal{\webworkProblemId}{}}{\question}{\titledquestion{\webworkProblemId}[\webworkProblemWeight]} + + + + + +\vfill +\goodbreak +\hrule +\nobreak +\smallskip + + + +\end{questions} +\end{multicols*} + + + +\newpage% +\setcounter{page}{1}% + + + +\newpage% +\setcounter{page}{1}% + + + +\end{document} + + + diff --git a/assets/hardcopyThemes/oneColumn.xml b/assets/hardcopyThemes/oneColumn.xml new file mode 100644 index 0000000000..a6f764b0ca --- /dev/null +++ b/assets/hardcopyThemes/oneColumn.xml @@ -0,0 +1,68 @@ + + + + +This theme uses the LaTeX exam class to manage page headers and footers, and +question enumeration. + + + +\documentclass[11pt]{exam} +\usepackage{webwork2} +\usepackage[text={6.5in,9in},centering]{geometry} +\extraheadheight[2pc]{0pt} +% This removes the margin for questions from the exam class. +\renewcommand{\questionshook}{\leftmargin=0pt\labelwidth=-\labelsep} +\makeatletter +\qformat{{\bfseries \webworkLocalizeProblem~\thequestiontitle.} \if@placepoints{\bfseries\footnotesize(\thepoints)}\fi \hfill} +\makeatother +\parindent=0pt +\pagestyle{headandfoot} +\begin{document} + + + +\firstpageheader{\webworkAssignmentCourseInfo}{}{\webworkUserInfo} +\runningheader{}{}{} +\footer{}{\webworkPageNumber}{} + + + +\smallskip +\hrule +\begin{questions} + + + +\ifthenelse{\equal{\webworkProblemNumber}{}}{\question}{\titledquestion{\webworkProblemNumber}[\webworkProblemWeight]} + + + + + +\vfill +\goodbreak +\hrule +\nobreak +\smallskip + + + +\end{questions} + + + +\newpage% +\setcounter{page}{1}% + + + +\newpage% +\setcounter{page}{1}% + + + +\end{document} + + + diff --git a/assets/hardcopyThemes/twoColumn.xml b/assets/hardcopyThemes/twoColumn.xml new file mode 100644 index 0000000000..f26c36f81d --- /dev/null +++ b/assets/hardcopyThemes/twoColumn.xml @@ -0,0 +1,73 @@ + + + + +This theme uses the LaTeX exam class to manage page headers and footers, and +question enumeration. With two columns. + + + +\documentclass[10pt]{exam} +\usepackage{webwork2} +\usepackage[text={7in,9in},centering]{geometry} +\usepackage{multicol} +\setlength{\columnsep}{.25in} +\setlength{\columnseprule}{.4pt} +\extraheadheight[2pc]{0pt} +% This removes the margin for questions from the exam class. +\renewcommand{\questionshook}{\leftmargin=0pt\labelwidth=-\labelsep} +\makeatletter +\qformat{{\bfseries \webworkLocalizeProblem~\thequestiontitle.} \if@placepoints{\bfseries\footnotesize(\thepoints)}\fi \hfill} +\makeatother +\parindent=0pt +\pagestyle{headandfoot} +\begin{document} + + + +\firstpageheader{\webworkAssignmentCourseInfo}{}{\webworkUserInfo} +\runningheader{}{}{} +\footer{}{\webworkPageNumber}{} + + + +\smallskip +\hrule +\begin{multicols*}{2} +\begin{questions} + + + +\ifthenelse{\equal{\webworkProblemNumber}{}}{\question}{\titledquestion{\webworkProblemNumber}[\webworkProblemWeight]} + + + + + +\vfill +\goodbreak +\hrule +\nobreak +\smallskip + + + +\end{questions} +\end{multicols*} + + + +\newpage% +\setcounter{page}{1}% + + + +\newpage% +\setcounter{page}{1}% + + + +\end{document} + + + diff --git a/conf/snippets/blankProblem.pg b/assets/pg/blankProblem.pg similarity index 100% rename from conf/snippets/blankProblem.pg rename to assets/pg/blankProblem.pg diff --git a/conf/snippets/blankProblem2.pg b/assets/pg/blankProblem2.pg similarity index 100% rename from conf/snippets/blankProblem2.pg rename to assets/pg/blankProblem2.pg diff --git a/conf/snippets/defaultSetHeader.pg b/assets/pg/defaultSetHeader.pg similarity index 99% rename from conf/snippets/defaultSetHeader.pg rename to assets/pg/defaultSetHeader.pg index 03bbbeefec..e971a1d78d 100644 --- a/conf/snippets/defaultSetHeader.pg +++ b/assets/pg/defaultSetHeader.pg @@ -29,8 +29,6 @@ HTML BEGIN_PGML [@ MODES(TeX => $TeX, HTML => $HTML) @]** - -[$setDescription] [% You can replace this comment with information that would appear in both screen and hardcopy set headers. %] END_PGML diff --git a/conf/snippets/newProblem.pg b/assets/pg/newProblem.pg similarity index 100% rename from conf/snippets/newProblem.pg rename to assets/pg/newProblem.pg diff --git a/conf/snippets/hardcopyThemes/common/webwork2.sty b/assets/tex/webwork2.sty similarity index 51% rename from conf/snippets/hardcopyThemes/common/webwork2.sty rename to assets/tex/webwork2.sty index 000de8f4bf..f9b80e7306 100644 --- a/conf/snippets/hardcopyThemes/common/webwork2.sty +++ b/assets/tex/webwork2.sty @@ -1,6 +1,28 @@ \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{webwork2}[2023/06/26 version 2.18] +% packages that are used by webwork2 itself, probably by Hardcopy.pm +\usepackage{path} +\discretionaries |~!@$%^&*()_+`-=#{"}[]:;'<>,.?\/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789| +\usepackage{listings} +\lstset{basicstyle=\ttfamily,breaklines=true,aboveskip=0pt,belowskip=0pt} +\usepackage{pg} + +% support for languages and fonts when XeLaTeX in use +% note pg.sty loads iftex package +\ifXeTeX + \usepackage{fontspec} + \usepackage{xunicode} + \usepackage{polyglossia} + \setdefaultlanguage{english} + % WeBWorK used Control+_ = ^_ for verbatim... so we change its charcode + \catcode`\_=12 +\fi + +% used in convenience macros below +\usepackage{hyperref} +\usepackage{ifthen} + % These macros may be overridden with WeBWorK environment variables \def\webworkCourseName{} \def\webworkCourseTitle{} @@ -19,17 +41,23 @@ \def\webworkDueDate{} \def\webworkAnswerDate{} \def\webworkPrettySetId{} +\def\webworkProblemId{} +\def\webworkProblemNumber{} +\def\webworkProblemWeight{} % These words/phrases may be overridden for localization -% They are used in subsequent macros \def\webworkLocalizeAssignment{Assignment} +\def\webworkLocalizeSet{Set} +\def\webworkLocalizeProblem{Problem} +\def\webworkLocalizeUsername{Username} \def\webworkLocalizeFullCreditBy{full credit by} \def\webworkLocalizeCloses{closes} \def\webworkLocalizeSection{Section} \def\webworkLocalizeRecitation{Recitation} \def\webworkLocalizePage{Page} +\def\webworkLocalizePoint{point} -% These would typically be used in a header or footer +% These conveniences could be used in a header or footer \newcommand{\webworkAssignmentCourseInfo} {% \ifx\webworkSetId\empty\else{% @@ -48,3 +76,25 @@ \newcommand{\webworkPageNumber}{\webworkLocalizePage~\thepage} +% These macros declare copyright in the footer of the last page. +\newcommand{\webworkSetCopyrightFooter}{% +\@ifpackageloaded{fancyhdr}% +{% +\fancyfoot[L]{\raisebox{-0.325cm}{\includegraphics[width=3cm]{webwork_logo.png}}}% +\fancyfoot[C]{\small\sffamily Generated by WeBWorK, \copyright~The~WeBWorK~Project.}% +\fancyfoot[R]{\url{openwebwork.org}}% +\pagestyle{fancy}% +\clearpage% +}% +{}% +\@ifclassloaded{exam}% +{% +\footer{\raisebox{-0.325cm}{\includegraphics[width=3cm]{webwork_logo.png}}}% +{\small\sffamily Generated by WeBWorK, \copyright~The~WeBWorK~Project.}% +{\url{openwebwork.org}}% +\clearpage% +}% +{}% +} + + diff --git a/conf/snippets/hardcopyThemes/common/webwork_logo.png b/assets/tex/webwork_logo.png similarity index 100% rename from conf/snippets/hardcopyThemes/common/webwork_logo.png rename to assets/tex/webwork_logo.png diff --git a/bin/check_latex b/bin/check_latex index 111e71c5c8..447eae10b9 100755 --- a/bin/check_latex +++ b/bin/check_latex @@ -49,10 +49,15 @@ die $@ if $@; my $pdflatex_cmd = "cd $temp_dir && " . "TEXINPUTS=$ENV{WEBWORK_ROOT}/bin:" - . shell_quote($ce->{webworkDirs}{texinputs_common}) . ':' + . shell_quote($ce->{webworkDirs}{assetsTex}) . ':' . shell_quote("$ce->{pg}{directories}{assetsTex}") . ': ' . $ce->{externalPrograms}{pdflatex} - . ' -interaction nonstopmode check_latex.tex > check_latex.nfo 2>&1'; + . ' -interaction nonstopmode check_latex_article.tex > check_latex.nfo 2>&1 &&' + . "TEXINPUTS=$ENV{WEBWORK_ROOT}/bin:" + . shell_quote($ce->{webworkDirs}{assetsTex}) . ':' + . shell_quote("$ce->{pg}{directories}{assetsTex}") . ': ' + . $ce->{externalPrograms}{pdflatex} + . ' -interaction nonstopmode check_latex_exam.tex >> check_latex.nfo 2>&1'; if ((system $pdflatex_cmd) >> 8) { if (open(my $fh, '<', "$temp_dir/check_latex.nfo")) { diff --git a/bin/check_latex_article.tex b/bin/check_latex_article.tex new file mode 100644 index 0000000000..56c1ae8270 --- /dev/null +++ b/bin/check_latex_article.tex @@ -0,0 +1,44 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% WeBWorK Online Homework Delivery System +% Copyright © 2000-2023 The WeBWorK Project, https://github.com/openwebwork +% +% This program is free software; you can redistribute it and/or modify it under +% the terms of either: (a) the GNU General Public License as published by the +% Free Software Foundation; either version 2, or (at your option) any later +% version, or (b) the "Artistic License" which comes with this package. +% +% This program is distributed in the hope that it will be useful, but WITHOUT +% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the +% Artistic License for more details. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\documentclass[10pt]{article} + +\usepackage{webwork2} + +% theme dependencies +\usepackage[text={7.5in,9in},centering]{geometry} +\usepackage{fancyhdr} +\usepackage{multicol} +\usepackage{tcolorbox} + +\usepackage[active,textmath,displaymath]{preview} % needed for dvipng + +\setlength{\columnsep}{.25in} +\setlength{\columnseprule}{.4pt} + +\begin{document} +\voffset=-0.8in +\begin{multicols}{2} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +Testing the LaTeX set up for WeBWorK. +%{\includegraphics[width = 3.5 in]{prob03av8.pdf}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\end{multicols} +\vfill +\end{document} diff --git a/bin/check_latex.tex b/bin/check_latex_exam.tex similarity index 93% rename from bin/check_latex.tex rename to bin/check_latex_exam.tex index b9cfe2de62..0a2cec7231 100644 --- a/bin/check_latex.tex +++ b/bin/check_latex_exam.tex @@ -15,9 +15,15 @@ \documentclass[10pt]{exam} -\input{packages.tex} +\usepackage{webwork2} +% theme dependencies \usepackage[text={7.5in,9in},centering]{geometry} +\usepackage{multicol} +\ifXeTeX + \usepackage{bidi} +\fi + \usepackage[active,textmath,displaymath]{preview} % needed for dvipng \setlength{\columnsep}{.25in} @@ -25,9 +31,6 @@ \renewcommand{\questionshook}{\leftmargin=0pt\labelwidth=-\labelsep} -\input{CAPA.tex} -\input{PGML.tex} - \begin{document} \voffset=-0.8in \begin{multicols}{2} diff --git a/bin/check_modules.pl b/bin/check_modules.pl index 6aef84329d..51cbd95bff 100755 --- a/bin/check_modules.pl +++ b/bin/check_modules.pl @@ -149,6 +149,7 @@ =head1 DESCRIPTION Types::Serialiser URI::Escape UUID::Tiny + XML::LibXML XML::Parser XML::Parser::EasyTree XML::Writer diff --git a/conf/defaults.config b/conf/defaults.config index 46f79a06e8..4fff1421f5 100644 --- a/conf/defaults.config +++ b/conf/defaults.config @@ -137,34 +137,6 @@ $institutionLogo = 'maa_logo.svg'; $institutionURL = 'http://www.maa.org'; $institutionName = 'MAA (Mathematical Association of America)'; -################################################################################ -# Hardcopy Theme -################################################################################ - -# Available Hardcopy themes (located in snippets) -# (their "internal" name and their pretty name for end users) -$hardcopyThemeNames = { - oneColumn => 'One Column', - twoColumn => 'Two Columns', - #'XeLaTeX-oneColumn' => 'English - one Column', - #'XeLaTeX-twoColumn' => 'English - two Columns', - #'XeLaTeX-Hebrew-oneColumn' => 'Hebrew/English - one Column', - #'XeLaTeX-Hebrew-twoColumn' => 'Hebrew/English - two Columns', -}; - -# This is needed to enforce an order that the options are presented when making a hardcopy -$hardcopyThemes = [ - 'oneColumn', - 'twoColumn', - #'XeLaTeX-oneColumn', - #'XeLaTeX-twoColumn', - #'XeLaTeX-Hebrew-oneColumn', - #'XeLaTeX-Hebrew-twoColumn', -]; - -# Default Hardcopy theme -$hardcopyTheme = "twoColumn"; - ################################################################################ # Achievements ################################################################################ @@ -273,9 +245,15 @@ $webworkDirs{uploadCache} = "$webworkDirs{DATA}/uploads"; # Location of utility programs. $webworkDirs{bin} = "$webworkDirs{root}/bin"; -# Location of configuration files, templates, snippets, etc. +# Location of configuration files. $webworkDirs{conf} = "$webworkDirs{root}/conf"; +# Location of assets (tex, pg, themes) +$webworkDirs{assets} = "$webworkDirs{root}/assets"; + +# Location of the distribution hardcopy themes. +$webworkDirs{hardcopyThemes} = "$webworkDirs{assets}/hardcopyThemes"; + # Location of course directories. $webworkDirs{courses} = "$webwork_courses_dir" || "$webworkDirs{root}/courses"; @@ -291,9 +269,8 @@ $webworkDirs{tmp} = "$webworkDirs{root}/tmp"; # $webworkDirs{valid_symlinks} = ["$webworkDirs{courses}/modelCourse/templates","/ww2/common/sets"]; $webworkDirs{valid_symlinks} = []; -# Location of the common tex input files packages.tex, CAPA.tex, and PGML.tex -# used for hardcopy generation. -$webworkDirs{texinputs_common} = "$webworkDirs{root}/conf/snippets/hardcopyThemes/common"; +# Location of the webwork2.sty and its dependencies used for hardcopy generation. +$webworkDirs{assetsTex} = "$webworkDirs{assets}/tex"; ################################################################################ ##### The following locations are web-accessible. @@ -387,6 +364,9 @@ $courseDirs{scoring} = "$courseDirs{root}/scoring"; # Location of PG templates and set definition files. $courseDirs{templates} = "$courseDirs{root}/templates"; +# Location of hardcopy theme files. +$courseDirs{hardcopyThemes} = "$courseDirs{templates}/hardcopyThemes"; + # Location of course achievement files. $courseDirs{achievements} = "$courseDirs{templates}/achievements"; $courseDirs{achievements_html} = "$courseDirs{html}/achievements"; #contains badge icons @@ -419,45 +399,44 @@ $webworkFiles{environment} = "$webworkDirs{conf}/defaults.c $webworkFiles{equationCacheDB} = ""; # "$webworkDirs{DATA}/equationcache"; ################################################################################ -# Hardcopy snippets are used in constructing a TeX file for hardcopy output. -# They should contain TeX code unless otherwise noted. -################################################################################ - -# The setHeader precedes each set in hardcopy output. It is a PG file. -# This is the default file which is used if a specific files is not selected -$webworkFiles{hardcopySnippets}{setHeader} = "$webworkDirs{conf}/snippets/defaultSetHeader.pg"; - -################################################################################ -# In general the following files are determined by which hardcopy theme you -# are using however you can set these variables to override the theme settings. -# Note: These will override all themes. +# Hardcopy Theme ################################################################################ -# The preamble is the first thing in the TeX file. There is one preamble for the -# entire tex file, even when multiple sets for multiple users are in one PDF -#$webworkFiles{hardcopySnippets}{preamble} = "$webworkDirs{conf}/snippets/hardcopyPreamble.tex"; - -# The PG file for setHeader is used, and is followed by this hardcopySetHeader.tex -# file. This happens for each set-user combination in a hardcopy that with multiple -# set-user combinations. This file can contain tex-specific header settings that -# should not need to be in a set's PG header file. For example, if the theme uses -# two columns, that should be set here. -#$webworkFiles{hardcopySnippets}{setTexHeader} = "$webworkDirs{conf}/snippets/hardcopySetHeader.tex"; - -# The problem divider goes between problems. -#$webworkFiles{hardcopySnippets}{problemDivider} = "$webworkDirs{conf}/snippets/hardcopyProblemDivider.tex"; +# Hardcopy themes are .xml files. See assets/hardcopThemes/README.md for details +# about their structure. The site themes are files in $webworkDirs{hardcopyThemes}. +# A course may have additional themes in $courseDirs{hardcopyThemes}. If two +# themes have the same filename, the theme from the course overrides the theme +# for the site. The array below defines which site themes are enabled. This array +# can be overridden, in particular in a course config file to enable course-local +# themes. -# The set footer is a tex file that goes after each set-user combination. -#$webworkFiles{hardcopySnippets}{setFooter} = "$webworkDirs{conf}/snippets/hardcopySetFooter.tex"; +$hardcopyThemes = [ + 'basic.xml', + 'basicTwoCol.xml', + 'boxed.xml', + 'boxedRows.xml', + 'boxedTwoCol.xml', + 'classic.xml', + 'classicTwoCol.xml', + 'empty.xml', + #'hebrew.xml', + #'hebrewTwoCol.xml', + 'oneColumn.xml', + 'twoColumn.xml', +]; -# The set divider goes between sets (in multiset output). -#$webworkFiles{hardcopySnippets}{setDivider} = "$webworkDirs{conf}/snippets/hardcopySetDivider.tex"; +# Default hardcopy themes (should be one of the enabled themes) +$hardcopyTheme = 'twoColumn.xml'; +$hardcopyThemePGEditor = 'empty.xml'; -# The user divider does between users (in multiuser output). -#$webworkFiles{hardcopySnippets}{userDivider} = "$webworkDirs{conf}/snippets/hardcopyUserDivider.tex"; +################################################################################ +# Hardcopy snippets are used in constructing a TeX file for hardcopy output. +# They should contain TeX code unless otherwise noted. +################################################################################ -# The postamble is the last thing in the TeX file. -#$webworkFiles{hardcopySnippets}{postamble} = "$webworkDirs{conf}/snippets/hardcopyPostamble.tex"; +# The setHeader precedes each set in hardcopy output. It is a PG file. +# This is the default file which is used if a specific files is not selected +$webworkFiles{hardcopySnippets}{setHeader} = "$webworkDirs{assets}/pg/defaultSetHeader.pg"; ################################################################################ ##### Screen snippets are used when displaying problem sets on the screen. @@ -465,12 +444,12 @@ $webworkFiles{hardcopySnippets}{setHeader} = "$webworkDirs{conf}/snippets/de # The set header is displayed on the problem set page. It is a PG file. # This is the default file which is used if a specific files is not selected -$webworkFiles{screenSnippets}{setHeader} = "$webworkDirs{conf}/snippets/defaultSetHeader.pg"; +$webworkFiles{screenSnippets}{setHeader} = "$webworkDirs{assets}/pg/defaultSetHeader.pg"; # A PG template for creation of new problems. -$webworkFiles{screenSnippets}{blankProblem} = "$webworkDirs{conf}/snippets/newProblem.pg"; +$webworkFiles{screenSnippets}{blankProblem} = "$webworkDirs{assets}/pg/newProblem.pg"; -# A site info "message of the day" file +# A site info "message of the day" file $webworkFiles{site_info} = "$webworkDirs{htdocs}/site_info.txt"; ################################################################################ @@ -1400,8 +1379,8 @@ $pg{options}{enableProgressBar} = 1; # Site wide overrides are entered into the file localOverrides.conf ################################################################################ # This is loaded before the $ConfigValues definition, so that the if values of -# $hardcopyThemes and $hardcopyThemeNames are overridden in localOverrides.conf, -# then those values are used and shown in the course configuration. +# $hardcopyThemes are overridden in localOverrides.conf, then those values are +# used and shown in the course configuration. include("conf/localOverrides.conf"); ################################################################################ @@ -1529,18 +1508,35 @@ $ConfigValues = [ hashVar => '{siteDefaults}->{timezone}' }, { - var => 'hardcopyTheme', - doc => x('Hardcopy Theme'), + var => 'hardcopyThemes', + doc => x('Enabled Hardcopy Themes'), doc2 => x( - 'There are currently two hardcopy themes to choose from: One Column and Two Columns. The Two ' - . 'Columns theme is the traditional hardcopy format. The One Column theme uses the full page ' - . 'width for each column' + 'Choose which PDF hardcopy themes are available. The possibilites include the site theme options as ' + . 'well as themes in the hardcopyThemes folder for the course. Your selection must be saved ' + . 'and then the page must be reloaded before the new list of enabled themes will be reflected ' + . 'in the selection that follows.' ), - values => $hardcopyThemes, - labels => $hardcopyThemeNames, + values => [qw(empty.xml)], + type => 'checkboxlist', + min => 1, + hashVar => '{hardcopyThemes}' + }, + { + var => 'hardcopyTheme', + doc => x('Hardcopy Theme'), + doc2 => x('Choose a layout/styling theme for PDF hardcopy production.'), + values => [qw(empty.xml)], type => 'popuplist', hashVar => '{hardcopyTheme}' }, + { + var => 'hardcopyThemePGEditor', + doc => x('Hardcopy Theme for Problem Editor'), + doc2 => x('Choose a layout/styling theme for PDF hardcopy production from the Prooblem Editor.'), + values => [qw(empty.xml)], + type => 'popuplist', + hashVar => '{hardcopyThemePGEditor}' + }, { var => 'showCourseHomeworkTotals', doc => x('Show Total Homework Grade on Grades Page'), diff --git a/conf/localOverrides.conf.dist b/conf/localOverrides.conf.dist index 1b24e96657..9e554eb305 100644 --- a/conf/localOverrides.conf.dist +++ b/conf/localOverrides.conf.dist @@ -106,7 +106,7 @@ $mail{feedbackRecipients} = [ # rather than a centrally-stored file shared by all courses. #$webworkFiles{hardcopySnippets}{setHeader} = "$courseDirs{templates}/defaultSetHeader.pg"; -#$webworkFiles{hardcopySnippets}{setHeader} = "$courseDirs{templates}/myHardCopyHeaderFile.pg"; +#$webworkFiles{hardcopySnippets}{setHeader} = "$courseDirs{templates}/myHardcopyHeaderFile.pg"; # The set header is displayed on the problem set page. It is a PG file. # One of these default files which is used if a specific files is not selected @@ -517,54 +517,39 @@ $mail{feedbackRecipients} = [ #$permissionLevels{show_answer_group_info} = "admin"; #$permissionLevels{modify_tags} = "admin"; +################################################################################ +# Hardcopy Theme ################################################################################ -# Available Hardcopy themes (located in snippets) - adds four XeLaTeX themes -# using polyglossia for multilingual support and fontspec. -# The "oneColumn" and "twoColumn" options require pdflatex be installed on the server -# For using any of the XeLaTeX options, xelatex must be installed on the server -# (on Ubuntu this is in the texlive-xetex package). -# Note: restrict options to only pdflatex options, or only xelatex options, -# and not both types. -# Set $externalPrograms{pdflatex} to use either pdflatex or xelatex, -# depending on which flavor of themes you are enabling. -# Using --no-shell-escape is important for security reasons. -#$externalPrograms{pdflatex} ="/usr/bin/xelatex --no-shell-escape"; +# Hardcopy themes are .xml files. See assets/hardcopThemes/README.md for details +# about their structure. The site themes are files in $webworkDirs{hardcopyThemes}. +# A course may have additional themes in $courseDirs{hardcopyThemes}. If two +# themes have the same filename, the theme from the course overrides the theme +# for the site. The array below defines which site themes are enabled. This array +# can be overridden, in particular in a course config file to enable course-local +# themes. -# Available Hardcopy themes (located in snippets) -# (their "internal" name and their pretty name for end users) -#$hardcopyThemeNames = { - #oneColumn => 'One Column', - #twoColumn => 'Two Columns', - #'XeLaTeX-oneColumn' => 'English - one Column', - #'XeLaTeX-twoColumn' => 'English - two Columns', - #'XeLaTeX-Hebrew-oneColumn' => 'Hebrew/English - one Column', - #'XeLaTeX-Hebrew-twoColumn' => 'Hebrew/English - two Columns', -#}; - -# This is needed to enforce an order that the options are presented when making a hardcopy #$hardcopyThemes = [ - #'oneColumn', - #'twoColumn', - #'XeLaTeX-oneColumn', - #'XeLaTeX-twoColumn', - #'XeLaTeX-Hebrew-oneColumn', - #'XeLaTeX-Hebrew-twoColumn', +# 'empty.xml', +# 'basic.xml', +# 'basicTwoCol.xml', +# 'classic.xml', +# 'classicTwoCol.xml', +# 'oneColumn.xml', +# 'twoColumn.xml', +# 'boxed.xml', +# 'boxedTwoCol.xml', +# 'boxedRows.xml', +# 'hebrew.xml', +# 'hebrewTwoCol.xml', #]; +# The Hebrew themes need to use xelatex. Uncomment the following for xelatex +#$externalPrograms{pdflatex} ="/usr/bin/xelatex --no-shell-escape"; -# Change default Hardcopy theme -# Be sure to choose one that is enabled! -#$hardcopyTheme = "XeLaTeX-twoColumn"; - -# Location of the common tex input files packages.tex, CAPA.tex, and PGML.tex -# used for hardcopy generation. Uncomment the following line and adjust the -# path as needed to customize the TeX input files used for all themes in -# hardcopy generation. This location must contain the three files named above. -#$webworkDirs{texinputs_common} = "$webworkDirs{root}/conf/snippets/hardcopyThemes/common"; - -################################################################################ - +# Default hardcopy themes (should be one of the enabled themes) +#$hardcopyTheme = 'twoColumn.xml'; +#$hardcopyThemePGEditor = 'empty.xml'; ################################################################################ # Webwork Caliper diff --git a/conf/snippets/hardcopyPostamble.tex b/conf/snippets/hardcopyPostamble.tex deleted file mode 120000 index 771dc2cf0b..0000000000 --- a/conf/snippets/hardcopyPostamble.tex +++ /dev/null @@ -1 +0,0 @@ -hardcopyThemes/twoColumn/./hardcopyPostamble.tex \ No newline at end of file diff --git a/conf/snippets/hardcopyPreamble.tex b/conf/snippets/hardcopyPreamble.tex deleted file mode 120000 index 1da24c668e..0000000000 --- a/conf/snippets/hardcopyPreamble.tex +++ /dev/null @@ -1 +0,0 @@ -hardcopyThemes/twoColumn/./hardcopyPreamble.tex \ No newline at end of file diff --git a/conf/snippets/hardcopyProblemDivider.tex b/conf/snippets/hardcopyProblemDivider.tex deleted file mode 120000 index 4bf7c28873..0000000000 --- a/conf/snippets/hardcopyProblemDivider.tex +++ /dev/null @@ -1 +0,0 @@ -hardcopyThemes/twoColumn/./hardcopyProblemDivider.tex \ No newline at end of file diff --git a/conf/snippets/hardcopySetDivider.tex b/conf/snippets/hardcopySetDivider.tex deleted file mode 120000 index 37f12b35fb..0000000000 --- a/conf/snippets/hardcopySetDivider.tex +++ /dev/null @@ -1 +0,0 @@ -hardcopyThemes/twoColumn/./hardcopySetDivider.tex \ No newline at end of file diff --git a/conf/snippets/hardcopySetFooter.tex b/conf/snippets/hardcopySetFooter.tex deleted file mode 120000 index ce410efe66..0000000000 --- a/conf/snippets/hardcopySetFooter.tex +++ /dev/null @@ -1 +0,0 @@ -hardcopyThemes/twoColumn/./hardcopySetFooter.tex \ No newline at end of file diff --git a/conf/snippets/hardcopySetHeader.tex b/conf/snippets/hardcopySetHeader.tex deleted file mode 120000 index c970303121..0000000000 --- a/conf/snippets/hardcopySetHeader.tex +++ /dev/null @@ -1 +0,0 @@ -hardcopyThemes/twoColumn/./hardcopySetHeader.tex \ No newline at end of file diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopyPostamble.tex b/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopyPostamble.tex deleted file mode 100644 index 8e831736a7..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopyPostamble.tex +++ /dev/null @@ -1,3 +0,0 @@ - -\vfill -\end{document} diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopyPreamble.tex b/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopyPreamble.tex deleted file mode 100644 index a6ee049787..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopyPreamble.tex +++ /dev/null @@ -1,57 +0,0 @@ -\batchmode -\documentclass[11pt]{exam} -\input{packages.tex} - -\usepackage[text={7.5in,9in},centering]{geometry} - -% For XeLaTeX + polyglossia - using Hebrew and the Culmus fonts -\usepackage{fontspec} -\usepackage{xunicode} - -% Load the polyglossia package to support multiple languages. -% see https://ctan.org/pkg/polyglossia -\usepackage{polyglossia} - -% bidi needs to be loaded AFTER caption, xcolor, and geometry. -\usepackage{bidi} - -\setdefaultlanguage{hebrew} -\setotherlanguage{english} -\setmainfont{Frank Ruehl CLM} -\setmonofont{Miriam Mono CLM} -\setsansfont{Simple CLM} - -% When using default English -% Use \begin{hebrew} block of text \end{hebrew} for paragraphs. -% -% When using default Hebrew -% Use \begin{hebrew} block of text \end{hebrew} for paragraphs. - -% WeBWorK used Control+_ = ^_ for verbatim... so we change its charcode -\catcode`\=12 - -% This removes the margin for questions from the exam class. At this point we only use questions and not parts or -% subparts, but if those are used a similar thing will be needed for those as well. -\renewcommand{\questionshook}{\leftmargin=0pt\labelwidth=-\labelsep} - -\makeatletter -\qformat{{\bfseries שאלה \thequestiontitle.} \if@placepoints{\textenglish{\bfseries\footnotesize(\thepoints)}}\fi \hfill} -\makeatother - -\input{CAPA.tex} -\input{PGML.tex} - -% This needs a Hebrew localizations for -\def\webworkLocalizeAssignment{Assignment} -\def\webworkLocalizeFullCreditBy{full credit by} -\def\webworkLocalizeCloses{closes} -\def\webworkLocalizeSection{Section} -\def\webworkLocalizeRecitation{Recitation} -\def\webworkLocalizePage{Page} - -\pagestyle{headandfoot} -\firstpageheader{\webworkAssignmentCourseInfo}{}{\webworkUserInfo} -\runningheader{}{}{} -\footer{}{}{\webworkPageNumber} - -\begin{document} diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopyProblemDivider.tex b/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopyProblemDivider.tex deleted file mode 100644 index 12a723ba3f..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopyProblemDivider.tex +++ /dev/null @@ -1,6 +0,0 @@ - -\vfill -\goodbreak -\hrule -\nobreak -\smallskip diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopySetDivider.tex b/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopySetDivider.tex deleted file mode 100644 index a66b59253a..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopySetDivider.tex +++ /dev/null @@ -1,4 +0,0 @@ - -\newpage% -\setcounter{page}{1}% - diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopySetFooter.tex b/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopySetFooter.tex deleted file mode 100644 index c8716a38ba..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopySetFooter.tex +++ /dev/null @@ -1 +0,0 @@ -\input{copyright.tex} diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopySetHeader.pg b/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopySetHeader.pg deleted file mode 100644 index 8b13789179..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopySetHeader.pg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopySetHeader.tex b/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopySetHeader.tex deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopyUserDivider.tex b/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopyUserDivider.tex deleted file mode 100644 index 25cb763f38..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-oneColumn/hardcopyUserDivider.tex +++ /dev/null @@ -1,3 +0,0 @@ - -\newpage% -\setcounter{page}{1}% diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopyPostamble.tex b/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopyPostamble.tex deleted file mode 100644 index 8e831736a7..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopyPostamble.tex +++ /dev/null @@ -1,3 +0,0 @@ - -\vfill -\end{document} diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopyPreamble.tex b/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopyPreamble.tex deleted file mode 100644 index 648e0f0ee4..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopyPreamble.tex +++ /dev/null @@ -1,61 +0,0 @@ -\batchmode -\documentclass[10pt]{exam} -\input{packages.tex} - -\usepackage[text={7.5in,9in},centering]{geometry} - -% For XeLaTeX + polyglossia - using Hebrew and the Culmus fonts -\usepackage{fontspec} -\usepackage{xunicode} - -% Load the polyglossia package to support multiple languages. -% see https://ctan.org/pkg/polyglossia -\usepackage{polyglossia} - -% bidi needs to be loaded AFTER caption, xcolor, and geometry. -\usepackage{bidi} - -\setdefaultlanguage{hebrew} -\setotherlanguage{english} -\setmainfont{Frank Ruehl CLM} -\setmonofont{Miriam Mono CLM} -\setsansfont{Simple CLM} - -% When using default English -% Use \begin{hebrew} block of text \end{hebrew} for paragraphs. -% -% When using default Hebrew -% Use \begin{hebrew} block of text \end{hebrew} for paragraphs. - -% WeBWorK used Control+_ = ^_ for verbatim... so we change its charcode -\catcode`\=12 - -\setlength{\columnsep}{.25in} -\setlength{\columnseprule}{.4pt} - -% This removes the margin for questions from the exam class. At this point we only use questions and not parts or -% subparts, but if those are used a similar thing will be needed for those as well. -\renewcommand{\questionshook}{\leftmargin=0pt\labelwidth=-\labelsep} - -\makeatletter -\qformat{{\bfseries שאלה \thequestiontitle.} \if@placepoints{\textenglish{\bfseries\footnotesize(\thepoints)}}\fi \hfill} -\makeatother - -\input{CAPA.tex} -\input{PGML.tex} - -% This needs a Hebrew localizations for -\def\webworkLocalizeAssignment{Assignment} -\def\webworkLocalizeFullCreditBy{full credit by} -\def\webworkLocalizeCloses{closes} -\def\webworkLocalizeSection{Section} -\def\webworkLocalizeRecitation{Recitation} -\def\webworkLocalizePage{Page} - -\pagestyle{headandfoot} -\firstpageheader{\webworkAssignmentCourseInfo}{}{\webworkUserInfo} -\runningheader{}{}{} -\footer{}{}{\webworkPageNumber} - -\begin{document} -\voffset=-0.8in diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopyProblemDivider.tex b/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopyProblemDivider.tex deleted file mode 100644 index 12a723ba3f..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopyProblemDivider.tex +++ /dev/null @@ -1,6 +0,0 @@ - -\vfill -\goodbreak -\hrule -\nobreak -\smallskip diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopySetDivider.tex b/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopySetDivider.tex deleted file mode 100644 index 95f4a1bd28..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopySetDivider.tex +++ /dev/null @@ -1,4 +0,0 @@ - -\newpage% -\setcounter{page}{1}% - diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopySetFooter.tex b/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopySetFooter.tex deleted file mode 100644 index d5c2b3c4da..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopySetFooter.tex +++ /dev/null @@ -1,2 +0,0 @@ -\input{copyright.tex} -\end{multicols*} diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopySetHeader.pg b/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopySetHeader.pg deleted file mode 100644 index 8b13789179..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopySetHeader.pg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopySetHeader.tex b/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopySetHeader.tex deleted file mode 100644 index 18edf8e9bf..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopySetHeader.tex +++ /dev/null @@ -1 +0,0 @@ -\begin{multicols*}{2} diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopyUserDivider.tex b/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopyUserDivider.tex deleted file mode 100644 index efe003a0a5..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-Hebrew-twoColumn/hardcopyUserDivider.tex +++ /dev/null @@ -1,3 +0,0 @@ - -\newpage% -\setcounter{page}{1}% diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopyPostamble.tex b/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopyPostamble.tex deleted file mode 100644 index 8e831736a7..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopyPostamble.tex +++ /dev/null @@ -1,3 +0,0 @@ - -\vfill -\end{document} diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopyPreamble.tex b/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopyPreamble.tex deleted file mode 100644 index e8ce0a4832..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopyPreamble.tex +++ /dev/null @@ -1,51 +0,0 @@ -\batchmode -\documentclass[11pt]{exam} -\input{packages.tex} - -\usepackage[text={7.5in,9in},centering]{geometry} - -% For XeLaTeX + polyglossia -\usepackage{fontspec} -\usepackage{xunicode} - -% Load the polyglossia package to support multiple languages. -% see https://ctan.org/pkg/polyglossia -\usepackage{polyglossia} -\setdefaultlanguage{english} -% Can add additional languages -%\setotherlanguage{supported_language} - -% Can add additional languages -%\setotherlanguage{supported_language} - -% Can set TTF/OTF fonts, ex with -%\setmainfont{main font name} -%\setmonofont{mono font name} -%\setsansfont{sans font name} - -% If needed - can load the bidi package to support RTL and LTR languages -% using automatic direction changes (where it works) for Unicode UTF-8 -% encoded text. -% The bidi package needs to be loaded AFTER caption, xcolor, and geometry. -%\usepackage{bidi} - -% WeBWorK used Control+_ = ^_ for verbatim... so we change its charcode -\catcode`\=12 - -% This removes the margin for questions from the exam class. At this point we only use questions and not parts or -% subparts, but if those are used a similar thing will be needed for those as well. -\renewcommand{\questionshook}{\leftmargin=0pt\labelwidth=-\labelsep} - -\makeatletter -\qformat{{\bfseries Problem \thequestiontitle.} \if@placepoints{\bfseries\footnotesize(\thepoints)}\fi \hfill} -\makeatother - -\input{CAPA.tex} -\input{PGML.tex} - -\pagestyle{headandfoot} -\firstpageheader{\webworkAssignmentCourseInfo}{}{\webworkUserInfo} -\runningheader{}{}{} -\footer{}{}{\webworkPageNumber} - -\begin{document} diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopyProblemDivider.tex b/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopyProblemDivider.tex deleted file mode 100644 index 12a723ba3f..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopyProblemDivider.tex +++ /dev/null @@ -1,6 +0,0 @@ - -\vfill -\goodbreak -\hrule -\nobreak -\smallskip diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopySetDivider.tex b/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopySetDivider.tex deleted file mode 100644 index efe003a0a5..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopySetDivider.tex +++ /dev/null @@ -1,3 +0,0 @@ - -\newpage% -\setcounter{page}{1}% diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopySetFooter.tex b/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopySetFooter.tex deleted file mode 100644 index c8716a38ba..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopySetFooter.tex +++ /dev/null @@ -1 +0,0 @@ -\input{copyright.tex} diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopySetHeader.pg b/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopySetHeader.pg deleted file mode 100644 index 8b13789179..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopySetHeader.pg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopySetHeader.tex b/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopySetHeader.tex deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopyUserDivider.tex b/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopyUserDivider.tex deleted file mode 100644 index 25cb763f38..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-oneColumn/hardcopyUserDivider.tex +++ /dev/null @@ -1,3 +0,0 @@ - -\newpage% -\setcounter{page}{1}% diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopyPostamble.tex b/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopyPostamble.tex deleted file mode 100644 index 8e831736a7..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopyPostamble.tex +++ /dev/null @@ -1,3 +0,0 @@ - -\vfill -\end{document} diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopyPreamble.tex b/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopyPreamble.tex deleted file mode 100644 index f8f2bc6b90..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopyPreamble.tex +++ /dev/null @@ -1,54 +0,0 @@ -\batchmode -\documentclass[10pt]{exam} -\input{packages.tex} - -\usepackage[text={7.5in,9in},centering]{geometry} - -% For XeLaTeX + polyglossia -\usepackage{fontspec} -\usepackage{xunicode} - -% Load the polyglossia package to support multiple languages. -% see https://ctan.org/pkg/polyglossia -\usepackage{polyglossia} -\setdefaultlanguage{english} -% Can add additional languages -%\setotherlanguage{supported_language} - -% Can add additional languages -%\setotherlanguage{supported_language} - -% Can set TTF/OTF fonts, ex with -%\setmainfont{main font name} -%\setmonofont{mono font name} -%\setsansfont{sans font name} - -% If needed - can load the bidi package to support RTL and LTR languages -% using automatic direction changes (where it works) for Unicode UTF-8 -% encoded text. -% The bidi package needs to be loaded AFTER caption, xcolor, and geometry. -%\usepackage{bidi} - -% WeBWorK used Control+_ = ^_ for verbatim... so we change its charcode -\catcode`\=12 - -\setlength{\columnsep}{.25in} -\setlength{\columnseprule}{.4pt} - -% This removes the margin for questions from the exam class. At this point we only use questions and not parts or -% subparts, but if those are used a similar thing will be needed for those as well. -\renewcommand{\questionshook}{\leftmargin=0pt\labelwidth=-\labelsep} - -\makeatletter -\qformat{{\bfseries Problem \thequestiontitle.} \if@placepoints{\bfseries\footnotesize(\thepoints)}\fi \hfill} -\makeatother - -\input{CAPA.tex} -\input{PGML.tex} - -\pagestyle{headandfoot} -\firstpageheader{\webworkAssignmentCourseInfo}{}{\webworkUserInfo} -\runningheader{}{}{} -\footer{}{}{\webworkPageNumber} - -\begin{document} diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopyProblemDivider.tex b/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopyProblemDivider.tex deleted file mode 100644 index 12a723ba3f..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopyProblemDivider.tex +++ /dev/null @@ -1,6 +0,0 @@ - -\vfill -\goodbreak -\hrule -\nobreak -\smallskip diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopySetDivider.tex b/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopySetDivider.tex deleted file mode 100644 index 95f4a1bd28..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopySetDivider.tex +++ /dev/null @@ -1,4 +0,0 @@ - -\newpage% -\setcounter{page}{1}% - diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopySetFooter.tex b/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopySetFooter.tex deleted file mode 100644 index d5c2b3c4da..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopySetFooter.tex +++ /dev/null @@ -1,2 +0,0 @@ -\input{copyright.tex} -\end{multicols*} diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopySetHeader.pg b/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopySetHeader.pg deleted file mode 100644 index 8b13789179..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopySetHeader.pg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopySetHeader.tex b/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopySetHeader.tex deleted file mode 100644 index 18edf8e9bf..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopySetHeader.tex +++ /dev/null @@ -1 +0,0 @@ -\begin{multicols*}{2} diff --git a/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopyUserDivider.tex b/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopyUserDivider.tex deleted file mode 100644 index efe003a0a5..0000000000 --- a/conf/snippets/hardcopyThemes/XeLaTeX-twoColumn/hardcopyUserDivider.tex +++ /dev/null @@ -1,3 +0,0 @@ - -\newpage% -\setcounter{page}{1}% diff --git a/conf/snippets/hardcopyThemes/common/CAPA.tex b/conf/snippets/hardcopyThemes/common/CAPA.tex deleted file mode 100644 index 11d7d32fac..0000000000 --- a/conf/snippets/hardcopyThemes/common/CAPA.tex +++ /dev/null @@ -1,15 +0,0 @@ -% capa tex macros - -\newcommand{\capa}{{\sl C\kern-.10em\raise-.00ex\hbox{\rm A}\kern-.22em% -{\sl P}\kern-.14em\kern-.01em{\rm A}}} - -\newenvironment{choicelist} -{\begin{list}{} - {\setlength{\rightmargin}{0in}\setlength{\leftmargin}{0.13in} - \setlength{\topsep}{0.05in}\setlength{\itemsep}{0.022in} - \setlength{\parsep}{0in}\setlength{\belowdisplayskip}{0.04in} - \setlength{\abovedisplayskip}{0.05in} - \setlength{\abovedisplayshortskip}{-0.04in} - \setlength{\belowdisplayshortskip}{0.04in}} - } -{\end{list}} diff --git a/conf/snippets/hardcopyThemes/common/PGML.tex b/conf/snippets/hardcopyThemes/common/PGML.tex deleted file mode 100644 index a4b8c0c649..0000000000 --- a/conf/snippets/hardcopyThemes/common/PGML.tex +++ /dev/null @@ -1,71 +0,0 @@ -% definitions for PGML - -\newcount\pgmlCount -\newdimen\pgmlPercent -\newdimen\pgmlPixels - -\pgmlPixels=.5pt - -{\catcode`\^^M=\active% - \gdef\pgmlSetup{% - \pgmlPercent=.01\hsize% - \parskip=0pt% - \def\par{\ifmmode\else\endgraf\fi\ignorespaces}% - \catcode`\^^M=\active% - \def^^M{\ifmmode\else\space\fi\ignorespaces}} - \global\let^^M\par}% - -\def\pgmlIndent{\par\advance\leftskip by 2em \advance\pgmlPercent by .02em \pgmlCount=0}% -\def\pgmlbulletItem{\par\indent\llap{$\bullet$ }\ignorespaces}% -\def\pgmldiscItem{\par\indent\llap{$\bullet$ }\ignorespaces}% -\def\pgmlcircleItem{\par\indent\llap{$\circ$ }\ignorespaces}% -\def\pgmlsquareItem{\par\indent\llap{\vrule height 1ex width .75ex depth -.25ex\ }\ignorespaces}% -\def\pgmlnumericItem{\par\indent\advance\pgmlCount by 1 \llap{\the\pgmlCount. }\ignorespaces}% -\def\pgmlalphaItem{\par\indent{\advance\pgmlCount by `\a \llap{\char\pgmlCount. }}\advance\pgmlCount by 1\ignorespaces}% -\def\pgmlAlphaItem{\par\indent{\advance\pgmlCount by `\A \llap{\char\pgmlCount. }}\advance\pgmlCount by 1\ignorespaces}% -\def\pgmlromanItem{\par\indent\advance\pgmlCount by 1 \llap{\romannumeral\pgmlCount. }\ignorespaces}% -\def\pgmlRomanItem{\par\indent\advance\pgmlCount by 1 \llap{\uppercase\expandafter{\romannumeral\pgmlCount}. }\ignorespaces}% - -\def\pgmlCenter{% - \par \parfillskip=0pt - \advance\leftskip by 0pt plus .5\hsize - \advance\rightskip by 0pt plus .5\hsize - \def\pgmlBreak{\break}% -}% -\def\pgmlRight{% - \par \parfillskip=0pt - \advance\leftskip by 0pt plus \hsize - \def\pgmlBreak{\break}% -}% - -\def\pgmlBreak{\\}% - -\def\pgmlHeading#1{% - \par\bfseries - \ifcase#1 \or\huge \or\LARGE \or\large \or\normalsize \or\footnotesize \or\scriptsize \fi -}% - -\def\pgmlRule#1#2{% - \par\noindent - \hbox{% - \strut% - \dimen1=\ht\strutbox% - \advance\dimen1 by -#2% - \divide\dimen1 by 2% - \advance\dimen2 by -\dp\strutbox% - \raise\dimen1\hbox{\vrule width #1 height #2 depth 0pt}% - }% - \par -}% - -\def\pgmlIC#1{\futurelet\pgmlNext\pgmlCheckIC}% -\def\pgmlCheckIC{\ifx\pgmlNext\pgmlSpace \/\fi}% -{\def\getSpace#1{\global\let\pgmlSpace= }\getSpace{} }% - -{\catcode`\ =12\global\let\pgmlSpaceChar= }% -{\catcode`\^^M=\active% - \gdef\pgmlPreformatted{\par\small\ttfamily\hsize=10\hsize\obeyspaces\catcode`\^^M=\active\let^^M=\pgmlNL\pgmlNL}}% -\def\pgmlNL{\par\bgroup\catcode`\ =12\pgmlTestSpace}% -\def\pgmlTestSpace{\futurelet\next\pgmlTestChar}% -\def\pgmlTestChar{\ifx\next\pgmlSpaceChar\ \pgmlTestNext\fi\egroup}% -\def\pgmlTestNext\fi\egroup#1{\fi\pgmlTestSpace}% diff --git a/conf/snippets/hardcopyThemes/common/copyright.tex b/conf/snippets/hardcopyThemes/common/copyright.tex deleted file mode 100644 index 5464bd3017..0000000000 --- a/conf/snippets/hardcopyThemes/common/copyright.tex +++ /dev/null @@ -1 +0,0 @@ -\footer{\raisebox{-0.325cm}{\includegraphics[width=3cm]{webwork_logo.png}}}{\small\sffamily Generated by WeBWorK, \copyright~The~WeBWorK~Project, \url{https://openwebwork.org}.}{Page \thepage} diff --git a/conf/snippets/hardcopyThemes/common/packages.tex b/conf/snippets/hardcopyThemes/common/packages.tex deleted file mode 100644 index d14b451ad6..0000000000 --- a/conf/snippets/hardcopyThemes/common/packages.tex +++ /dev/null @@ -1,32 +0,0 @@ -\usepackage{amsmath,amsfonts,amssymb,multicol} -\usepackage{booktabs,tabularx,colortbl,caption,xcolor} -\usepackage[version=4]{mhchem} -\usepackage{path} -\discretionaries |~!@$%^&*()_+`-=#{"}[]:;'<>,.?\/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789| - -\usepackage{iftex} -\ifXeTeX - \usepackage{graphicx} -\else - \usepackage[pdftex]{graphicx} - \usepackage{epstopdf} % allows use of eps files with pdftex - \usepackage[utf8]{inputenc} - \usepackage{eurosym} % the euro symbol - \DeclareUnicodeCharacter{20AC}{\euro} % make it possible to use the UTF-8 character for the euro symbol in problems -\fi - -\usepackage{listings} -\lstset{basicstyle=\ttfamily,breaklines=true,aboveskip=0pt,belowskip=0pt} -\usepackage{hyperref} -\usepackage{webwork2} -\usepackage{pg} - -\pagestyle{plain} - -\def\endline{\bigskip\hrule width \hsize height 0.8pt } -\newcommand{\lt}{<} -\newcommand{\gt}{>} -\newcommand{\less}{<} -\newcommand{\grt}{>} - -\parindent=0pt diff --git a/conf/snippets/hardcopyThemes/oneColumn/hardcopyPostamble.tex b/conf/snippets/hardcopyThemes/oneColumn/hardcopyPostamble.tex deleted file mode 100644 index 8e831736a7..0000000000 --- a/conf/snippets/hardcopyThemes/oneColumn/hardcopyPostamble.tex +++ /dev/null @@ -1,3 +0,0 @@ - -\vfill -\end{document} diff --git a/conf/snippets/hardcopyThemes/oneColumn/hardcopyPreamble.tex b/conf/snippets/hardcopyThemes/oneColumn/hardcopyPreamble.tex deleted file mode 100644 index fcf2ff0faf..0000000000 --- a/conf/snippets/hardcopyThemes/oneColumn/hardcopyPreamble.tex +++ /dev/null @@ -1,23 +0,0 @@ -\batchmode -\documentclass[11pt]{exam} -\input{packages.tex} - -\usepackage[text={7.5in,9in},centering]{geometry} - -% This removes the margin for questions from the exam class. At this point we only use questions and not parts or -% subparts, but if those are used a similar thing will be needed for those as well. -\renewcommand{\questionshook}{\leftmargin=0pt\labelwidth=-\labelsep} - -\makeatletter -\qformat{{\bfseries Problem \thequestiontitle.} \if@placepoints{\bfseries\footnotesize(\thepoints)}\fi \hfill} -\makeatother - -\input{CAPA.tex} -\input{PGML.tex} - -\pagestyle{headandfoot} -\firstpageheader{\webworkAssignmentCourseInfo}{}{\webworkUserInfo} -\runningheader{}{}{} -\footer{}{}{\webworkPageNumber} - -\begin{document} diff --git a/conf/snippets/hardcopyThemes/oneColumn/hardcopyProblemDivider.tex b/conf/snippets/hardcopyThemes/oneColumn/hardcopyProblemDivider.tex deleted file mode 100644 index 12a723ba3f..0000000000 --- a/conf/snippets/hardcopyThemes/oneColumn/hardcopyProblemDivider.tex +++ /dev/null @@ -1,6 +0,0 @@ - -\vfill -\goodbreak -\hrule -\nobreak -\smallskip diff --git a/conf/snippets/hardcopyThemes/oneColumn/hardcopySetDivider.tex b/conf/snippets/hardcopyThemes/oneColumn/hardcopySetDivider.tex deleted file mode 100644 index 25cb763f38..0000000000 --- a/conf/snippets/hardcopyThemes/oneColumn/hardcopySetDivider.tex +++ /dev/null @@ -1,3 +0,0 @@ - -\newpage% -\setcounter{page}{1}% diff --git a/conf/snippets/hardcopyThemes/oneColumn/hardcopySetFooter.tex b/conf/snippets/hardcopyThemes/oneColumn/hardcopySetFooter.tex deleted file mode 100644 index c8716a38ba..0000000000 --- a/conf/snippets/hardcopyThemes/oneColumn/hardcopySetFooter.tex +++ /dev/null @@ -1 +0,0 @@ -\input{copyright.tex} diff --git a/conf/snippets/hardcopyThemes/oneColumn/hardcopySetHeader.tex b/conf/snippets/hardcopyThemes/oneColumn/hardcopySetHeader.tex deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/conf/snippets/hardcopyThemes/oneColumn/hardcopyUserDivider.tex b/conf/snippets/hardcopyThemes/oneColumn/hardcopyUserDivider.tex deleted file mode 100644 index 25cb763f38..0000000000 --- a/conf/snippets/hardcopyThemes/oneColumn/hardcopyUserDivider.tex +++ /dev/null @@ -1,3 +0,0 @@ - -\newpage% -\setcounter{page}{1}% diff --git a/conf/snippets/hardcopyThemes/twoColumn/hardcopyPostamble.tex b/conf/snippets/hardcopyThemes/twoColumn/hardcopyPostamble.tex deleted file mode 100644 index 8e831736a7..0000000000 --- a/conf/snippets/hardcopyThemes/twoColumn/hardcopyPostamble.tex +++ /dev/null @@ -1,3 +0,0 @@ - -\vfill -\end{document} diff --git a/conf/snippets/hardcopyThemes/twoColumn/hardcopyPreamble.tex b/conf/snippets/hardcopyThemes/twoColumn/hardcopyPreamble.tex deleted file mode 100644 index d7d6f02fde..0000000000 --- a/conf/snippets/hardcopyThemes/twoColumn/hardcopyPreamble.tex +++ /dev/null @@ -1,25 +0,0 @@ -\batchmode -\documentclass[10pt]{exam} -\input{packages.tex} - -\usepackage[text={7.5in,9in},centering]{geometry} -\setlength{\columnsep}{.25in} -\setlength{\columnseprule}{.4pt} - -% This removes the margin for questions from the exam class. At this point we only use questions and not parts or -% subparts, but if those are used a similar thing will be needed for those as well. -\renewcommand{\questionshook}{\leftmargin=0pt\labelwidth=-\labelsep} - -\makeatletter -\qformat{{\bfseries Problem \thequestiontitle.} \if@placepoints{\bfseries\footnotesize(\thepoints)}\fi \hfill} -\makeatother - -\input{CAPA.tex} -\input{PGML.tex} - -\pagestyle{headandfoot} -\firstpageheader{\webworkAssignmentCourseInfo}{}{\webworkUserInfo} -\runningheader{}{}{} -\footer{}{}{\webworkPageNumber} - -\begin{document} diff --git a/conf/snippets/hardcopyThemes/twoColumn/hardcopyProblemDivider.tex b/conf/snippets/hardcopyThemes/twoColumn/hardcopyProblemDivider.tex deleted file mode 100644 index 12a723ba3f..0000000000 --- a/conf/snippets/hardcopyThemes/twoColumn/hardcopyProblemDivider.tex +++ /dev/null @@ -1,6 +0,0 @@ - -\vfill -\goodbreak -\hrule -\nobreak -\smallskip diff --git a/conf/snippets/hardcopyThemes/twoColumn/hardcopySetDivider.tex b/conf/snippets/hardcopyThemes/twoColumn/hardcopySetDivider.tex deleted file mode 100644 index 25cb763f38..0000000000 --- a/conf/snippets/hardcopyThemes/twoColumn/hardcopySetDivider.tex +++ /dev/null @@ -1,3 +0,0 @@ - -\newpage% -\setcounter{page}{1}% diff --git a/conf/snippets/hardcopyThemes/twoColumn/hardcopySetFooter.tex b/conf/snippets/hardcopyThemes/twoColumn/hardcopySetFooter.tex deleted file mode 100644 index d5c2b3c4da..0000000000 --- a/conf/snippets/hardcopyThemes/twoColumn/hardcopySetFooter.tex +++ /dev/null @@ -1,2 +0,0 @@ -\input{copyright.tex} -\end{multicols*} diff --git a/conf/snippets/hardcopyThemes/twoColumn/hardcopySetHeader.tex b/conf/snippets/hardcopyThemes/twoColumn/hardcopySetHeader.tex deleted file mode 100644 index 18edf8e9bf..0000000000 --- a/conf/snippets/hardcopyThemes/twoColumn/hardcopySetHeader.tex +++ /dev/null @@ -1 +0,0 @@ -\begin{multicols*}{2} diff --git a/conf/snippets/hardcopyThemes/twoColumn/hardcopyUserDivider.tex b/conf/snippets/hardcopyThemes/twoColumn/hardcopyUserDivider.tex deleted file mode 100644 index 25cb763f38..0000000000 --- a/conf/snippets/hardcopyThemes/twoColumn/hardcopyUserDivider.tex +++ /dev/null @@ -1,3 +0,0 @@ - -\newpage% -\setcounter{page}{1}% diff --git a/conf/snippets/hardcopyUserDivider.tex b/conf/snippets/hardcopyUserDivider.tex deleted file mode 120000 index 2c5b583baf..0000000000 --- a/conf/snippets/hardcopyUserDivider.tex +++ /dev/null @@ -1 +0,0 @@ -hardcopyThemes/twoColumn/./hardcopyUserDivider.tex \ No newline at end of file diff --git a/lib/HardcopyRenderedProblem.pm b/lib/HardcopyRenderedProblem.pm index ca375c1641..e4dc7d0bcd 100644 --- a/lib/HardcopyRenderedProblem.pm +++ b/lib/HardcopyRenderedProblem.pm @@ -30,6 +30,7 @@ use File::Path; use String::ShellQuote; use Archive::Zip qw(:ERROR_CODES); use Mojo::File qw(path tempdir); +use XML::LibXML; sub hardcopyRenderedProblem { my $ws = shift; # $ws is a WebworkWebservice object. @@ -126,11 +127,17 @@ sub generate_hardcopy_tex { my $src_file = $working_dir->child('hardcopy.tex'); # Copy the common tex files into the working directory - my $ce = $ws->c->ce; - my $common_dir = path($ce->{webworkDirs}{texinputs_common}); - for (qw{packages.tex webwork2.sty CAPA.tex PGML.tex copyright.tex webwork_logo.png}) { - eval { $common_dir->child($_)->copy_to($working_dir) }; - push(@$errors, qq{Failed to copy "$ce->{webworkDirs}{texinputs_common}/$_" into directory "$working_dir": $@}) + my $ce = $ws->c->ce; + my $assetsTex_dir = path($ce->{webworkDirs}{assetsTex}); + for (qw{webwork2.sty webwork_logo.png}) { + eval { $assetsTex_dir->child($_)->copy_to($working_dir) }; + push(@$errors, qq{Failed to copy "$ce->{webworkDirs}{assetsTex}/$_" into directory "$working_dir": $@}) + if $@; + } + my $pgAssetsTex_dir = path($ce->{pg}{directories}{assetsTex}); + for (qw{pg.sty PGML.tex CAPA.tex}) { + eval { $pgAssetsTex_dir->child($_)->copy_to($working_dir) }; + push(@$errors, qq{Failed to copy "$ce->{pg}{directories}{assetsTex}/$_" into directory "$working_dir": $@}) if $@; } my $pgsty = path("$ce->{pg}{directories}{assetsTex}/pg.sty"); @@ -185,7 +192,7 @@ sub generate_hardcopy_pdf { # Call pdflatex my $pdflatex_cmd = 'TEXINPUTS=.:' - . shell_quote($ws->c->ce->{webworkDirs}{texinputs_common}) . ':' + . shell_quote($ws->c->ce->{webworkDirs}{assetsTex}) . ':' . shell_quote($ws->c->ce->{pg}{directories}{assetsTex}) . ': ' . $ws->c->ce->{externalPrograms}{pdflatex} . ' > pdflatex.stdout 2> pdflatex.stderr hardcopy'; @@ -210,16 +217,28 @@ sub write_tex { my $c = $ws->c; my $ce = $c->ce; - # Determine snippets theme directory. - my $themeDir = "$ce->{webworkDirs}{conf}/snippets/hardcopyThemes/" - . ($ws->{inputs_ref}{hardcopy_theme} // $ce->{hardcopyTheme}); + # get theme + my $theme = $c->param('hardcopy_theme') // $ce->{hardcopyTheme}; + my $themeFile; + if (-e "$ce->{courseDirs}{hardcopyThemes}/$theme") { + $themeFile = "$ce->{courseDirs}{hardcopyThemes}/$theme"; + } elsif (-e "$ce->{webworkDirs}{hardcopyThemes}/$theme") { + $themeFile = "$ce->{webworkDirs}{hardcopyThemes}/$theme"; + } else { + push(@$errors, "Couldn't locate file for theme $theme."); + return join("\n", @$errors); + } + my $themeTree = XML::LibXML->load_xml(location => $themeFile); - write_tex_file($FH, $ce->{webworkFiles}{hardcopySnippets}{preamble} // "$themeDir/hardcopyPreamble.tex", $errors); - write_tex_file($FH, $ce->{webworkFiles}{hardcopySnippets}{setTexHeader} // "$themeDir/hardcopySetHeader.tex", - $errors); + print $FH '\\batchmode'; + print $FH $themeTree->findvalue('/theme/preamble'); + print $FH $themeTree->findvalue('/theme/presetheader'); + print $FH $themeTree->findvalue('/theme/postsetheader'); + print $FH $themeTree->findvalue('/theme/problemheader'); write_problem_tex($ws, $FH); - write_tex_file($FH, $ce->{webworkFiles}{hardcopySnippets}{setFooter} // "$themeDir/hardcopySetFooter.tex", $errors); - write_tex_file($FH, $ce->{webworkFiles}{hardcopySnippets}{postamble} // "$themeDir/hardcopyPostamble.tex", $errors); + print $FH $themeTree->findvalue('/theme/problemfooter'); + print $FH $themeTree->findvalue('/theme/setfooter'); + print $FH $themeTree->findvalue('/theme/postamble'); return; } @@ -271,13 +290,4 @@ sub write_problem_tex { return; } -sub write_tex_file { - my ($FH, $file, $errors) = @_; - - eval { print $FH path($file)->slurp }; - push(@$errors, qq{Failed to include TeX file "$file": $@}) if $@; - - return; -} - 1; diff --git a/lib/WeBWorK/ConfigObject/checkboxlist.pm b/lib/WeBWorK/ConfigObject/checkboxlist.pm index 359a8536a1..1f2aa764cd 100644 --- a/lib/WeBWorK/ConfigObject/checkboxlist.pm +++ b/lib/WeBWorK/ConfigObject/checkboxlist.pm @@ -32,7 +32,7 @@ sub convert_newval_source ($self, $use_current) { sub save_string ($self, $oldval, $use_current = 0) { my @newvals = $self->convert_newval_source($use_current); if ($self->{min} && scalar(@newvals) < $self->{min}) { - $self->{c}->addbadmessage("You need to select at least $self->{min} display mode."); + $self->{c}->addbadmessage(qq!You need to select at least $self->{min} option for "$self->{doc}".!); return '' if $use_current; return $self->save_string($oldval, 1); } diff --git a/lib/WeBWorK/ContentGenerator/Hardcopy.pm b/lib/WeBWorK/ContentGenerator/Hardcopy.pm index 4828387bab..113be83220 100644 --- a/lib/WeBWorK/ContentGenerator/Hardcopy.pm +++ b/lib/WeBWorK/ContentGenerator/Hardcopy.pm @@ -27,6 +27,7 @@ use File::Path; use File::Temp qw/tempdir/; use String::ShellQuote; use Archive::Zip qw(:ERROR_CODES); +use XML::LibXML; use WeBWorK::DB::Utils qw/user2global/; use WeBWorK::PG; @@ -437,6 +438,21 @@ sub display_form ($c) { } } + # Get labels for the hardcopy themes, which are attributes in the theme xml file + my %hardcopyLabels; + my $hardcopyThemeDirSite = $ce->{webworkDirs}{hardcopyThemes}; + opendir(my $dhS, $hardcopyThemeDirSite) || die "can't opendir $hardcopyThemeDirSite: $!"; + for my $hardcopyTheme (grep {/\.xml$/} sort readdir($dhS)) { + my $themeTree = XML::LibXML->load_xml(location => "$hardcopyThemeDirSite/$hardcopyTheme"); + $hardcopyLabels{$hardcopyTheme} = $themeTree->findvalue('/theme/@label'); + } + my $hardcopyThemeDirCourse = $ce->{courseDirs}{hardcopyThemes}; + opendir(my $dhC, $hardcopyThemeDirCourse) || die "can't opendir $hardcopyThemeDirCourse: $!"; + for my $hardcopyTheme (grep {/\.xml$/} sort readdir($dhC)) { + my $themeTree = XML::LibXML->load_xml(location => "$hardcopyThemeDirCourse/$hardcopyTheme"); + $hardcopyLabels{$hardcopyTheme} = $themeTree->findvalue('/theme/@label'); + } + return $c->include( 'ContentGenerator/Hardcopy/form', canShowCorrectAnswers => $canShowCorrectAnswers, @@ -451,7 +467,8 @@ sub display_form ($c) { formats => \@formats, default_format => $HC_DEFAULT_FORMAT, format_labels => \%format_labels, - can_change_theme => $perm_change_theme + hardcopyLabels => \%hardcopyLabels, + can_change_theme => $perm_change_theme, ); } @@ -656,31 +673,33 @@ sub generate_hardcopy_tex ($c, $temp_dir_path, $final_file_basename) { # Copy the common tex files into the bundle directory my $ce = $c->ce; - for (qw{packages.tex webwork2.sty CAPA.tex PGML.tex copyright.tex webwork_logo.png}) { + for (qw{webwork2.sty webwork_logo.png}) { my $cp_cmd = - "2>&1 $ce->{externalPrograms}{cp} " . shell_quote("$ce->{webworkDirs}{texinputs_common}/$_", $bundle_path); + "2>&1 $ce->{externalPrograms}{cp} " . shell_quote("$ce->{webworkDirs}{assetsTex}/$_", $bundle_path); my $cp_out = readpipe $cp_cmd; if ($?) { $c->add_error( 'Failed to copy "', - $c->tag('code', "$ce->{webworkDirs}{texinputs_common}/$_"), + $c->tag('code', "$ce->{webworkDirs}{assetsTex}/$_"), '" into directory "', $c->tag('code', $bundle_path), '":', $c->tag('br'), $c->tag('pre', $cp_out) ); } } - my $cp_cmd = - "2>&1 $ce->{externalPrograms}{cp} " . shell_quote("$ce->{pg}{directories}{assetsTex}/pg.sty", $bundle_path); - my $cp_out = readpipe $cp_cmd; - if ($?) { - $c->add_error( - 'Failed to copy "', - $c->tag('code', "$ce->{pg}{directories}{assetsTex}/pg.sty"), - '" into directory "', - $c->tag('code', $bundle_path), - '":', $c->tag('br'), $c->tag('pre', $cp_out) - ); + for (qw{pg.sty PGML.tex CAPA.tex}) { + my $cp_cmd = + "2>&1 $ce->{externalPrograms}{cp} " . shell_quote("$ce->{pg}{directories}{assetsTex}/$_", $bundle_path); + my $cp_out = readpipe $cp_cmd; + if ($?) { + $c->add_error( + 'Failed to copy "', + $c->tag('code', "$ce->{pg}{directories}{assetsTex}/$_"), + '" into directory "', + $c->tag('code', $bundle_path), + '":', $c->tag('br'), $c->tag('pre', $cp_out) + ); + } } # Attempt to copy image files used into the working directory. @@ -752,7 +771,7 @@ sub generate_hardcopy_pdf ($c, $temp_dir_path, $final_file_basename) { my $pdflatex_cmd = "cd " . shell_quote($temp_dir_path) . " && " . "TEXINPUTS=.:" - . shell_quote($c->ce->{webworkDirs}{texinputs_common}) . ':' + . shell_quote($c->ce->{webworkDirs}{assetsTex}) . ':' . shell_quote($c->ce->{pg}{directories}{assetsTex}) . ': ' . $c->ce->{externalPrograms}{pdflatex} . " >pdflatex.stdout 2>pdflatex.stderr hardcopy"; @@ -824,33 +843,40 @@ async sub write_multiuser_tex ($c, $FH, $userIDsRef, $setIDsRef) { my @userIDs = @$userIDsRef; my @setIDs = @$setIDsRef; - # get snippets - my $theme = $c->param('hardcopy_theme') // $ce->{hardcopyTheme}; - my $themeDir = $ce->{webworkDirs}{conf} . '/snippets/hardcopyThemes/' . $theme; - my $preamble = $ce->{webworkFiles}{hardcopySnippets}{preamble} // "$themeDir/hardcopyPreamble.tex"; - my $postamble = $ce->{webworkFiles}{hardcopySnippets}{postamble} // "$themeDir/hardcopyPostamble.tex"; - my $divider = $ce->{webworkFiles}{hardcopySnippets}{userDivider} // "$themeDir/hardcopyUserDivider.tex"; + # get theme + my $theme = $c->param('hardcopy_theme') // $ce->{hardcopyTheme}; + my $themeFile; + if (-e "$ce->{courseDirs}{hardcopyThemes}/$theme") { + $themeFile = "$ce->{courseDirs}{hardcopyThemes}/$theme"; + } elsif (-e "$ce->{webworkDirs}{hardcopyThemes}/$theme") { + $themeFile = "$ce->{webworkDirs}{hardcopyThemes}/$theme"; + } else { + $c->add_error("Couldn't locate file for theme $theme."); + return; + } + my $themeTree = XML::LibXML->load_xml(location => $themeFile); # write preamble - $c->write_tex_file($FH, $preamble); - print $FH '\\def\\webworkCourseName{' . handle_underbar($ce->{courseName}) . "}\n"; - print $FH '\\def\\webworkCourseTitle{' . handle_underbar($c->db->getSettingValue('courseTitle')) . "}\n"; + print $FH "\\batchmode\n"; + print $FH $themeTree->findvalue('/theme/preamble'); + print $FH '\\def\\webworkCourseName{' . handle_underbar($ce->{courseName}) . "}%\n"; + print $FH '\\def\\webworkCourseTitle{' . handle_underbar($c->db->getSettingValue('courseTitle')) . "}%\n"; print $FH '\\def\\webworkCourseURL{' - . handle_underbar($ce->{server_root_url} . $ce->{webwork_url} . '/' . $ce->{courseName}) . "}\n"; + . handle_underbar($ce->{server_root_url} . $ce->{webwork_url} . '/' . $ce->{courseName}) . "}%\n"; # write section for each user while (defined(my $userID = shift @userIDs)) { - await $c->write_multiset_tex($FH, $userID, @setIDs); - $c->write_tex_file($FH, $divider) if @userIDs; # divide users, but not after the last user + await $c->write_multiset_tex($FH, $userID, $themeTree, @setIDs); + print $FH $themeTree->findvalue('/theme/userdivider'); } # write postamble - $c->write_tex_file($FH, $postamble); + print $FH $themeTree->findvalue('/theme/postamble'); return; } -async sub write_multiset_tex ($c, $FH, $targetUserID, @setIDs) { +async sub write_multiset_tex ($c, $FH, $targetUserID, $themeTree, @setIDs) { my $ce = $c->ce; my $db = $c->db; @@ -865,21 +891,16 @@ async sub write_multiset_tex ($c, $FH, $targetUserID, @setIDs) { return; } - # get set divider - my $theme = $c->param('hardcopy_theme') // $ce->{hardcopyTheme}; - my $themeDir = $ce->{webworkDirs}->{conf} . '/snippets/hardcopyThemes/' . $theme; - my $divider = $ce->{webworkFiles}->{hardcopySnippets}->{setDivider} // "$themeDir/hardcopySetDivider.tex"; - # write each set while (defined(my $setID = shift @setIDs)) { - await $c->write_set_tex($FH, $TargetUser, $setID); - $c->write_tex_file($FH, $divider) if @setIDs; # divide sets, but not after the last set + await $c->write_set_tex($FH, $TargetUser, $themeTree, $setID); + print $FH $themeTree->findvalue('/theme/setdivider'); # divide sets, but not after the last set } return; } -async sub write_set_tex ($c, $FH, $TargetUser, $setID) { +async sub write_set_tex ($c, $FH, $TargetUser, $themeTree, $setID) { my $ce = $c->ce; my $db = $c->db; my $authz = $c->authz; @@ -939,15 +960,10 @@ async sub write_set_tex ($c, $FH, $TargetUser, $setID) { return; } - # get snippets - my $theme = $c->param('hardcopy_theme') // $ce->{hardcopyTheme}; - my $themeDir = $ce->{webworkDirs}{conf} . '/snippets/hardcopyThemes/' . $theme; + # get PG header my $header = $MergedSet->hardcopy_header ? $MergedSet->hardcopy_header : $ce->{webworkFiles}{hardcopySnippets}{setHeader}; if ($header eq 'defaultHeader') { $header = $ce->{webworkFiles}{hardcopySnippets}{setHeader}; } - my $texheader = $ce->{webworkFiles}{hardcopySnippets}{setTexHeader} // "$themeDir/hardcopySetHeader.tex"; - my $footer = $ce->{webworkFiles}{hardcopySnippets}{setFooter} // "$themeDir/hardcopySetFooter.tex"; - my $divider = $ce->{webworkFiles}{hardcopySnippets}{problemDivider} // "$themeDir/hardcopyProblemDivider.tex"; # get list of problem IDs my @problemIDs = map { $_->[2] } @@ -975,19 +991,19 @@ async sub write_set_tex ($c, $FH, $TargetUser, $setID) { # write environment variables as LaTeX macros for (qw(user_id student_id first_name last_name email_address section recitation)) { - print $FH '\\def\\webwork' . underscore_to_camel($_) . '{' . handle_underbar($TargetUser->{$_}) . "}\n" + print $FH '\\def\\webwork' . underscore_to_camel($_) . '{' . handle_underbar($TargetUser->{$_}) . "}%\n" if $TargetUser->{$_}; } for (qw(set_id description)) { - print $FH '\\def\\webwork' . underscore_to_camel($_) . '{' . handle_underbar($MergedSet->{$_}) . "}\n" + print $FH '\\def\\webwork' . underscore_to_camel($_) . '{' . handle_underbar($MergedSet->{$_}) . "}%\n" if $MergedSet->{$_}; } - print $FH '\\def\\webworkPrettySetId{' . handle_underbar($MergedSet->{set_id}, 1) . "}\n"; + print $FH '\\def\\webworkPrettySetId{' . handle_underbar($MergedSet->{set_id}, 1) . "}%\n"; for (qw(open_date due_date answer_date)) { if ($MergedSet->{$_}) { print $FH '\\def\\webwork' . underscore_to_camel($_) . '{' - . $c->formatDateTime($MergedSet->{$_}, $ce->{siteDefaults}{timezone}) . "}\n"; + . $c->formatDateTime($MergedSet->{$_}, $ce->{siteDefaults}{timezone}) . "}%\n"; } } # Leave reduced scoring date blank if it is disabled, or enabled but on (or somehow later) than the close date @@ -997,31 +1013,30 @@ async sub write_set_tex ($c, $FH, $TargetUser, $setID) { && $MergedSet->{reduced_scoring_date} < $MergedSet->{due_date}) { print $FH '\\def\\webworkReducedScoringDate{' - . $c->formatDateTime($MergedSet->{reduced_scoring_date}, $ce->{siteDefaults}{timezone}) . "}\n"; + . $c->formatDateTime($MergedSet->{reduced_scoring_date}, $ce->{siteDefaults}{timezone}) . "}%\n"; } - # write set header - await $c->write_problem_tex($FH, $TargetUser, $MergedSet, 0, $header); # 0 => pg file specified directly - - $c->write_tex_file($FH, $texheader); - - print $FH "\\medskip\\hrule\\nobreak\\smallskip\n\\begin{questions}\n"; + # write set header (theme presetheader, then PG header, then theme postsetheader) + print $FH $themeTree->findvalue('/theme/presetheader'); + await $c->write_problem_tex($FH, $TargetUser, $MergedSet, $themeTree, 0, $header); # 0 => pg file specified directly + print $FH $themeTree->findvalue('/theme/postsetheader'); # write each problem # for versioned problem sets (gateway tests) we like to include # problem numbers my $i = 1; while (my $problemID = shift @problemIDs) { - $c->write_tex_file($FH, $divider) if $i > 1; - $c->{versioned} = $i if $versioned; - await $c->write_problem_tex($FH, $TargetUser, $MergedSet, $problemID); + $c->{versioned} = $i if $versioned; + print $FH $themeTree->findvalue('/theme/problemdivider') if $i > 1; + await $c->write_problem_tex($FH, $TargetUser, $MergedSet, $themeTree, $problemID); $i++; } - print $FH "\\end{questions}\n"; + # attempt to claim copyright + print $FH '\\webworkSetCopyrightFooter'; # write footer - $c->write_tex_file($FH, $footer); + print $FH $themeTree->findvalue('/theme/setfooter'); return; } @@ -1044,7 +1059,7 @@ sub handle_underbar { return $string; } -async sub write_problem_tex ($c, $FH, $TargetUser, $MergedSet, $problemID = 0, $pgFile = undef) { +async sub write_problem_tex ($c, $FH, $TargetUser, $MergedSet, $themeTree, $problemID = 0, $pgFile = undef) { my $ce = $c->ce; my $db = $c->db; my $authz = $c->authz; @@ -1129,11 +1144,9 @@ async sub write_problem_tex ($c, $FH, $TargetUser, $MergedSet, $problemID = 0, $ # why does it only occur with hardcopy? # Include old answers if answers were requested. - my $formFields = {}; - if ($showCorrectAnswers || $printStudentAnswers) { - my %oldAnswers = decodeAnswers($MergedProblem->last_answer); - $formFields->{$_} = $oldAnswers{$_} foreach (keys %oldAnswers); - print $FH "%% decoded old answers, saved. (keys = " . join(',', keys(%oldAnswers)) . ")\n" if %oldAnswers; + my $oldAnswers = {}; + if ($printStudentAnswers) { + %{$oldAnswers} = decodeAnswers($MergedProblem->last_answer); } my $pg = await renderPG( @@ -1142,7 +1155,7 @@ async sub write_problem_tex ($c, $FH, $TargetUser, $MergedSet, $problemID = 0, $ $MergedSet, $MergedProblem, $MergedSet->psvn, - $formFields, + $oldAnswers, { # translation options displayMode => 'tex', showHints => $showHints, @@ -1250,20 +1263,25 @@ async sub write_problem_tex ($c, $FH, $TargetUser, $MergedSet, $problemID = 0, $ $id = $versioned; # this cannot be right? } + print $FH "\\def\\webworkProblemId{$id}%\n"; + print $FH "\\def\\webworkProblemNumber{" . ($versioned ? $versioned : $id) . "}%\n"; + my $problemValue = $MergedProblem->value; - if (defined($problemValue)) { - print $FH "\\titledquestion{$id}[$problemValue]\n"; - } else { - print $FH "\\titledquestion{$id}\n"; - } + print $FH "\\def\\webworkProblemWeight{$problemValue}%\n" if defined($problemValue); + + print $FH $themeTree->findvalue('/theme/problemheader'); if ($c->{can_show_source_file} && $c->param("show_source_file") eq "Yes") { print $FH "{\\footnotesize\\path|" . $MergedProblem->source_file . "|}\n"; } - print $FH "\\smallskip\n\n"; } + # Include old answers if answers were requested. + if ($printStudentAnswers) { + print $FH "%% decoded old answers, saved. (keys = " . join(',', keys(%{$oldAnswers})) . ")\n" if %{$oldAnswers}; + } + print $FH $body_text; my @ans_entry_order = defined($pg->{flags}->{ANSWER_ENTRY_ORDER}) ? @{ $pg->{flags}->{ANSWER_ENTRY_ORDER} } : (); @@ -1332,7 +1350,7 @@ async sub write_problem_tex ($c, $FH, $TargetUser, $MergedSet, $problemID = 0, $ print $FH $commentMsg if $comment; } - # write the list of correct answers is appropriate; ANSWER_ENTRY_ORDER + # write the list of correct answers if appropriate; ANSWER_ENTRY_ORDER # isn't defined for versioned sets? this seems odd FIXME GWCHANGE if ($showCorrectAnswers && $MergedProblem->problem_id != 0 && @ans_entry_order) { my $correctTeX = @@ -1349,16 +1367,11 @@ async sub write_problem_tex ($c, $FH, $TargetUser, $MergedSet, $problemID = 0, $ print $FH $correctTeX; } - return; -} - -sub write_tex_file ($c, $FH, $file) { - my $tex = eval { readFile($file) }; - if ($@) { - $c->add_error('Failed to include TeX file "', $c->tag('code', $file), '": ', $c->tag('pre', $@)); - } else { - print $FH $tex; + if ($problemID) { + print $FH $themeTree->findvalue('/theme/problemfooter'); } + + return; } ################################################################################ diff --git a/lib/WeBWorK/ContentGenerator/Instructor/Config.pm b/lib/WeBWorK/ContentGenerator/Instructor/Config.pm index 6d9a4107e4..c0b5266389 100644 --- a/lib/WeBWorK/ContentGenerator/Instructor/Config.pm +++ b/lib/WeBWorK/ContentGenerator/Instructor/Config.pm @@ -93,6 +93,20 @@ sub getConfigValues ($c, $ce) { opendir(my $dh, $themeDir) || die "can't opendir $themeDir: $!"; my $themes = [ grep { !/^\.{1,2}$/ && $_ ne 'layouts' } sort readdir($dh) ]; + # Get the list of all hardcopy theme files + my $hardcopyThemeDirSite = $ce->{webworkDirs}{hardcopyThemes}; + my $hardcopyThemeDirCourse = $ce->{courseDirs}{hardcopyThemes}; + opendir(my $dhS, $hardcopyThemeDirSite) || die "can't opendir $hardcopyThemeDirSite: $!"; + opendir(my $dhC, $hardcopyThemeDirCourse) || die "can't opendir $hardcopyThemeDirCourse: $!"; + my $hardcopyThemes = [ grep {/\.xml$/} (sort readdir($dhS), sort readdir($dhC)) ]; + # get unique file names + $hardcopyThemes = [ + sort(do { + my %seen; + grep { !$seen{$_}++ } @$hardcopyThemes; + }) + ]; + # get list of localization dictionaries my $localizeDir = $ce->{webworkDirs}{localize}; opendir(my $dh2, $localizeDir) || die "can't opendir $localizeDir: $!"; @@ -104,13 +118,18 @@ sub getConfigValues ($c, $ce) { ]; - # insert the anonymous array of theme folder names into configValues + # insert the anonymous array of theme names into configValues # FIXME? Is there a reason this is an array? Couldn't we replace this # with a hash and conceptually simplify this routine? MEG my $modifyThemes = sub { my $item = shift; - if (ref($item) =~ /HASH/ and $item->{var} eq 'defaultTheme') { - $item->{values} = $themes; + if (ref($item) =~ /HASH/ + && ($item->{var} =~ /^(defaultTheme|hardcopyThemes|hardcopyTheme|hardcopyThemePGEditor)$/)) + { + $item->{values} = $themes if ($item->{var} eq 'defaultTheme'); + $item->{values} = $ce->{hardcopyThemes} + if ($item->{var} eq 'hardcopyTheme' || $item->{var} eq 'hardcopyThemePGEditor'); + $item->{values} = $hardcopyThemes if ($item->{var} eq 'hardcopyThemes'); } }; my $modifyLanguages = sub { diff --git a/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm b/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm index 2600999e38..43b6a1d8ba 100644 --- a/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm +++ b/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm @@ -108,6 +108,7 @@ not exist. The path to the actual file being edited is stored in inputFilePath. =cut use File::Copy; +use XML::LibXML; use WeBWorK::Utils qw(jitar_id_to_seq not_blank path_is_subdir seq_to_jitar_id x surePathToFile readDirectory readFile max format_set_name_display); @@ -297,6 +298,23 @@ sub initialize ($c) { $c->stash->{problemContents} = $problemContents; + # Get labels for the hardcopy themes, so the templates can use them. + my %hardcopyLabels; + my $hardcopyThemeDirSite = $ce->{webworkDirs}{hardcopyThemes}; + opendir(my $dhS, $hardcopyThemeDirSite) || die "can't opendir $hardcopyThemeDirSite: $!"; + for my $hardcopyTheme (grep {/\.xml$/} sort readdir($dhS)) { + my $themeTree = XML::LibXML->load_xml(location => "$hardcopyThemeDirSite/$hardcopyTheme"); + $hardcopyLabels{$hardcopyTheme} = $themeTree->findvalue('/theme/@label'); + } + my $hardcopyThemeDirCourse = $ce->{courseDirs}{hardcopyThemes}; + opendir(my $dhC, $hardcopyThemeDirCourse) || die "can't opendir $hardcopyThemeDirCourse: $!"; + for my $hardcopyTheme (grep {/\.xml$/} sort readdir($dhC)) { + my $themeTree = XML::LibXML->load_xml(location => "$hardcopyThemeDirCourse/$hardcopyTheme"); + $hardcopyLabels{$hardcopyTheme} = $themeTree->findvalue('/theme/@label'); + } + $c->stash->{hardcopyLabels} = \%hardcopyLabels; + $c->stash->{hardcopyThemes} = $ce->{hardcopyThemes}; + $c->{prettyProblemNumber} = $c->{problemID} // ''; $c->{set} = $c->db->getGlobalSet($c->{setID}) if $c->{setID}; $c->{prettyProblemNumber} = join('.', jitar_id_to_seq($c->{prettyProblemNumber})) @@ -473,7 +491,7 @@ sub getFilePaths ($c) { } } else { # If the set record doesn't specify the filename for a header or it specifies the defaultHeader, - # then the set uses the default from snippets. + # then the set uses the default from assets/pg. $editFilePath = $ce->{webworkFiles}{screenSnippets}{setHeader} if $c->{file_type} eq 'set_header'; $editFilePath = $ce->{webworkFiles}{hardcopySnippets}{setHeader} diff --git a/templates/ContentGenerator/Hardcopy/form.html.ep b/templates/ContentGenerator/Hardcopy/form.html.ep index cd78a01eef..3abf00d416 100644 --- a/templates/ContentGenerator/Hardcopy/form.html.ep +++ b/templates/ContentGenerator/Hardcopy/form.html.ep @@ -149,16 +149,29 @@
- <%= maketext('Hardcopy Theme') %> -
- % for (@{ $ce->{hardcopyThemes} }) { - - % } -
+ <%= maketext('Hardcopy Theme:') %> + % if (@{ $ce->{hardcopyThemes} } <= 3) { +
+ % for (@{ $ce->{hardcopyThemes} }) { + + % } +
+ % } else { +
+ <%= select_field 'hardcopy_theme' => [ + map { [ + $hardcopyLabels->{$_} => $_, + $_ eq $ce->{hardcopyTheme} ? (selected => undef) : () + ] } @{ $ce->{hardcopyThemes} } + ], + id => 'action_hardcopy_theme_id', + class => 'form-select form-select-sm d-inline w-auto' =%> +
+ % }
diff --git a/templates/ContentGenerator/Instructor/PGProblemEditor/hardcopy_form.html.ep b/templates/ContentGenerator/Instructor/PGProblemEditor/hardcopy_form.html.ep index f963793e05..647d18c454 100644 --- a/templates/ContentGenerator/Instructor/PGProblemEditor/hardcopy_form.html.ep +++ b/templates/ContentGenerator/Instructor/PGProblemEditor/hardcopy_form.html.ep @@ -51,9 +51,9 @@
<%= select_field 'action.hardcopy.theme' => [ map { [ - $ce->{hardcopyThemeNames}{$_} => $_, - $_ eq $ce->{hardcopyTheme} ? (selected => undef) : () - ] } @{ $ce->{hardcopyThemes} } + stash('hardcopyLabels')->{$_} => $_, + $_ eq $c->ce->{hardcopyThemePGEditor} ? (selected => undef) : () + ] } @{ stash('hardcopyThemes') } ], id => 'action_hardcopy_theme_id', class => 'form-select form-select-sm d-inline w-auto' =%> diff --git a/templates/HelpFiles/Hardcopy.html.ep b/templates/HelpFiles/Hardcopy.html.ep index a95bdb384a..2980bf853e 100644 --- a/templates/HelpFiles/Hardcopy.html.ep +++ b/templates/HelpFiles/Hardcopy.html.ep @@ -42,7 +42,7 @@
<%= maketext('If selected, the file path of the problem source will be printed in the output.') %>
<%= maketext('Hardcopy Theme') %>
-
<%= maketext('This will determine if the output is in one or two columns.') %>
+
<%= maketext('Choose from the available hardcopy layout themes.') %>

<%== maketext('Once "Generate Hardcopy for selected sets and selected users" is clicked a file in the selected ' From 82c4b4e0872b3811309c0379a1ee5056bf65fc59 Mon Sep 17 00:00:00 2001 From: Alex Jordan Date: Thu, 13 Jul 2023 14:11:14 -0700 Subject: [PATCH 02/15] make all course harddcopy themes effectively enabled; enabling only applies now to site hardcopy theme files --- conf/defaults.config | 28 +++++++------ conf/localOverrides.conf.dist | 18 +++++---- lib/HardcopyRenderedProblem.pm | 2 +- lib/WeBWorK/ContentGenerator/Hardcopy.pm | 40 +++++++++++-------- .../ContentGenerator/Instructor/Config.pm | 33 ++++++++++----- .../Instructor/PGProblemEditor.pm | 18 ++++++--- .../ContentGenerator/Hardcopy/form.html.ep | 6 +-- .../PGProblemEditor/hardcopy_form.html.ep | 2 +- 8 files changed, 91 insertions(+), 56 deletions(-) diff --git a/conf/defaults.config b/conf/defaults.config index 4fff1421f5..8af0ca5416 100644 --- a/conf/defaults.config +++ b/conf/defaults.config @@ -404,12 +404,7 @@ $webworkFiles{equationCacheDB} = ""; # "$webworkDirs{DATA}/equa # Hardcopy themes are .xml files. See assets/hardcopThemes/README.md for details # about their structure. The site themes are files in $webworkDirs{hardcopyThemes}. -# A course may have additional themes in $courseDirs{hardcopyThemes}. If two -# themes have the same filename, the theme from the course overrides the theme -# for the site. The array below defines which site themes are enabled. This array -# can be overridden, in particular in a course config file to enable course-local -# themes. - +# $hardcopyThemes identifies which site themes are enabled. $hardcopyThemes = [ 'basic.xml', 'basicTwoCol.xml', @@ -425,7 +420,16 @@ $hardcopyThemes = [ 'twoColumn.xml', ]; -# Default hardcopy themes (should be one of the enabled themes) +# A course may have additional themes in $courseDirs{hardcopyThemes}. All such +# "course" hardcopy themes are effectively enabled and offered for use when +# selecting a hardcopy theme. You can move such files or rename them to not +# have a .xml extension if you don't want them to be offered for use. + +# If a course hardcopy theme has the same name as a site hardcopy theme, the +# course hardcopy theme is the one that is used. + +# Default hardcopy themes (should either be an enabled site theme or a theme in +# the course hardcopyThemes folder $hardcopyTheme = 'twoColumn.xml'; $hardcopyThemePGEditor = 'empty.xml'; @@ -1509,17 +1513,17 @@ $ConfigValues = [ }, { var => 'hardcopyThemes', - doc => x('Enabled Hardcopy Themes'), + doc => x('Enabled Site Hardcopy Themes'), doc2 => x( - 'Choose which PDF hardcopy themes are available. The possibilites include the site theme options as ' - . 'well as themes in the hardcopyThemes folder for the course. Your selection must be saved ' + 'Choose which of the site PDF hardcopy themes are available. In addition to the themes selected here, ' + . 'all themes in the course hardcopyThemes folder will be available. Your selection must be saved ' . 'and then the page must be reloaded before the new list of enabled themes will be reflected ' - . 'in the selection that follows.' + . 'in the selections that follows.' ), values => [qw(empty.xml)], type => 'checkboxlist', min => 1, - hashVar => '{hardcopyThemes}' + hashVar => '{hardcopyThemesSite}' }, { var => 'hardcopyTheme', diff --git a/conf/localOverrides.conf.dist b/conf/localOverrides.conf.dist index 9e554eb305..c9dbfeb08d 100644 --- a/conf/localOverrides.conf.dist +++ b/conf/localOverrides.conf.dist @@ -523,12 +523,7 @@ $mail{feedbackRecipients} = [ # Hardcopy themes are .xml files. See assets/hardcopThemes/README.md for details # about their structure. The site themes are files in $webworkDirs{hardcopyThemes}. -# A course may have additional themes in $courseDirs{hardcopyThemes}. If two -# themes have the same filename, the theme from the course overrides the theme -# for the site. The array below defines which site themes are enabled. This array -# can be overridden, in particular in a course config file to enable course-local -# themes. - +# $hardcopyThemes identifies which site themes are enabled. #$hardcopyThemes = [ # 'empty.xml', # 'basic.xml', @@ -547,7 +542,16 @@ $mail{feedbackRecipients} = [ # The Hebrew themes need to use xelatex. Uncomment the following for xelatex #$externalPrograms{pdflatex} ="/usr/bin/xelatex --no-shell-escape"; -# Default hardcopy themes (should be one of the enabled themes) +# A course may have additional themes in $courseDirs{hardcopyThemes}. All such +# "course" hardcopy themes are effectively enabled and offered for use when +# selecting a hardcopy theme. You can move such files or rename them to not +# have a .xml extension if you don't want them to be offered for use. + +# If a course hardcopy theme has the same name as a site hardcopy theme, the +# course hardcopy theme is the one that is used. + +# Default hardcopy themes (should either be an enabled site theme or a theme in +# the course hardcopyThemes folder #$hardcopyTheme = 'twoColumn.xml'; #$hardcopyThemePGEditor = 'empty.xml'; diff --git a/lib/HardcopyRenderedProblem.pm b/lib/HardcopyRenderedProblem.pm index e4dc7d0bcd..13a6ed84a8 100644 --- a/lib/HardcopyRenderedProblem.pm +++ b/lib/HardcopyRenderedProblem.pm @@ -218,7 +218,7 @@ sub write_tex { my $ce = $c->ce; # get theme - my $theme = $c->param('hardcopy_theme') // $ce->{hardcopyTheme}; + my $theme = $c->param('hardcopy_theme') // $ce->{hardcopyThemePGEditor}; my $themeFile; if (-e "$ce->{courseDirs}{hardcopyThemes}/$theme") { $themeFile = "$ce->{courseDirs}{hardcopyThemes}/$theme"; diff --git a/lib/WeBWorK/ContentGenerator/Hardcopy.pm b/lib/WeBWorK/ContentGenerator/Hardcopy.pm index 113be83220..d1198334b7 100644 --- a/lib/WeBWorK/ContentGenerator/Hardcopy.pm +++ b/lib/WeBWorK/ContentGenerator/Hardcopy.pm @@ -448,27 +448,35 @@ sub display_form ($c) { } my $hardcopyThemeDirCourse = $ce->{courseDirs}{hardcopyThemes}; opendir(my $dhC, $hardcopyThemeDirCourse) || die "can't opendir $hardcopyThemeDirCourse: $!"; - for my $hardcopyTheme (grep {/\.xml$/} sort readdir($dhC)) { + my @hardcopyThemesCourse = grep {/\.xml$/} sort readdir($dhC); + for my $hardcopyTheme (@hardcopyThemesCourse) { my $themeTree = XML::LibXML->load_xml(location => "$hardcopyThemeDirCourse/$hardcopyTheme"); - $hardcopyLabels{$hardcopyTheme} = $themeTree->findvalue('/theme/@label'); + $hardcopyLabels{$hardcopyTheme} = $themeTree->findvalue('/theme/@label') || $hardcopyTheme; } + my $hardcopyThemesAvailable = [ + sort(do { + my %seen; + grep { !$seen{$_}++ } (@{ $ce->{hardcopyThemes} }, @hardcopyThemesCourse); + }) + ]; return $c->include( 'ContentGenerator/Hardcopy/form', - canShowCorrectAnswers => $canShowCorrectAnswers, - multiuser => $perm_multiuser && $perm_multiset, - can_change_theme => $perm_change_theme, - users => \@users, - wantedSets => \@wantedSets, - setVersions => \@setVersions, - user => $user, - user_id => $user_id, - selected_set_id => $selected_set_id, - formats => \@formats, - default_format => $HC_DEFAULT_FORMAT, - format_labels => \%format_labels, - hardcopyLabels => \%hardcopyLabels, - can_change_theme => $perm_change_theme, + canShowCorrectAnswers => $canShowCorrectAnswers, + multiuser => $perm_multiuser && $perm_multiset, + can_change_theme => $perm_change_theme, + users => \@users, + wantedSets => \@wantedSets, + setVersions => \@setVersions, + user => $user, + user_id => $user_id, + selected_set_id => $selected_set_id, + formats => \@formats, + default_format => $HC_DEFAULT_FORMAT, + format_labels => \%format_labels, + hardcopyLabels => \%hardcopyLabels, + hardcopyThemesAvailable => $hardcopyThemesAvailable, + can_change_theme => $perm_change_theme, ); } diff --git a/lib/WeBWorK/ContentGenerator/Instructor/Config.pm b/lib/WeBWorK/ContentGenerator/Instructor/Config.pm index c0b5266389..85d3712214 100644 --- a/lib/WeBWorK/ContentGenerator/Instructor/Config.pm +++ b/lib/WeBWorK/ContentGenerator/Instructor/Config.pm @@ -93,17 +93,25 @@ sub getConfigValues ($c, $ce) { opendir(my $dh, $themeDir) || die "can't opendir $themeDir: $!"; my $themes = [ grep { !/^\.{1,2}$/ && $_ ne 'layouts' } sort readdir($dh) ]; - # Get the list of all hardcopy theme files - my $hardcopyThemeDirSite = $ce->{webworkDirs}{hardcopyThemes}; + # Get the list of all site hardcopy theme files + my $hardcopyThemeDirSite = $ce->{webworkDirs}{hardcopyThemes}; + opendir(my $dhS, $hardcopyThemeDirSite) || die "can't opendir $hardcopyThemeDirSite: $!"; + my $hardcopyThemesSite = [ grep {/\.xml$/} (sort readdir($dhS)) ]; my $hardcopyThemeDirCourse = $ce->{courseDirs}{hardcopyThemes}; - opendir(my $dhS, $hardcopyThemeDirSite) || die "can't opendir $hardcopyThemeDirSite: $!"; opendir(my $dhC, $hardcopyThemeDirCourse) || die "can't opendir $hardcopyThemeDirCourse: $!"; - my $hardcopyThemes = [ grep {/\.xml$/} (sort readdir($dhS), sort readdir($dhC)) ]; - # get unique file names - $hardcopyThemes = [ + my $hardcopyThemesCourse = [ grep {/\.xml$/} (sort readdir($dhC)) ]; + # get unique file names, merging lists from site and course folders + my $hardcopyThemes = [ sort(do { my %seen; - grep { !$seen{$_}++ } @$hardcopyThemes; + grep { !$seen{$_}++ } (@$hardcopyThemesSite, @$hardcopyThemesCourse); + }) + ]; + # get enabled site themes plus all course themes + my $hardcopyThemesAvailable = [ + sort(do { + my %seen; + grep { !$seen{$_}++ } (@{ $ce->{hardcopyThemes} }, @$hardcopyThemesCourse); }) ]; @@ -123,13 +131,16 @@ sub getConfigValues ($c, $ce) { # with a hash and conceptually simplify this routine? MEG my $modifyThemes = sub { my $item = shift; - if (ref($item) =~ /HASH/ - && ($item->{var} =~ /^(defaultTheme|hardcopyThemes|hardcopyTheme|hardcopyThemePGEditor)$/)) + if ( + ref($item) =~ /HASH/ + && ($item->{var} =~ + /^(defaultTheme|hardcopyThemesSite|hardcopyThemes|hardcopyTheme|hardcopyThemePGEditor)$/) + ) { $item->{values} = $themes if ($item->{var} eq 'defaultTheme'); - $item->{values} = $ce->{hardcopyThemes} + $item->{values} = $hardcopyThemesAvailable if ($item->{var} eq 'hardcopyTheme' || $item->{var} eq 'hardcopyThemePGEditor'); - $item->{values} = $hardcopyThemes if ($item->{var} eq 'hardcopyThemes'); + $item->{values} = $hardcopyThemesSite if ($item->{var} eq 'hardcopyThemes'); } }; my $modifyLanguages = sub { diff --git a/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm b/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm index 52e955d476..218026b503 100644 --- a/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm +++ b/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm @@ -303,16 +303,24 @@ sub initialize ($c) { opendir(my $dhS, $hardcopyThemeDirSite) || die "can't opendir $hardcopyThemeDirSite: $!"; for my $hardcopyTheme (grep {/\.xml$/} sort readdir($dhS)) { my $themeTree = XML::LibXML->load_xml(location => "$hardcopyThemeDirSite/$hardcopyTheme"); - $hardcopyLabels{$hardcopyTheme} = $themeTree->findvalue('/theme/@label'); + $hardcopyLabels{$hardcopyTheme} = $themeTree->findvalue('/theme/@label') || $hardcopyTheme; } my $hardcopyThemeDirCourse = $ce->{courseDirs}{hardcopyThemes}; opendir(my $dhC, $hardcopyThemeDirCourse) || die "can't opendir $hardcopyThemeDirCourse: $!"; - for my $hardcopyTheme (grep {/\.xml$/} sort readdir($dhC)) { + my @hardcopyThemesCourse = grep {/\.xml$/} sort readdir($dhC); + for my $hardcopyTheme (@hardcopyThemesCourse) { my $themeTree = XML::LibXML->load_xml(location => "$hardcopyThemeDirCourse/$hardcopyTheme"); - $hardcopyLabels{$hardcopyTheme} = $themeTree->findvalue('/theme/@label'); + $hardcopyLabels{$hardcopyTheme} = $themeTree->findvalue('/theme/@label') || $hardcopyTheme; } - $c->stash->{hardcopyLabels} = \%hardcopyLabels; - $c->stash->{hardcopyThemes} = $ce->{hardcopyThemes}; + my $hardcopyThemesAvailable = [ + sort(do { + my %seen; + grep { !$seen{$_}++ } (@{ $ce->{hardcopyThemes} }, @hardcopyThemesCourse); + }) + ]; + + $c->stash->{hardcopyLabels} = \%hardcopyLabels; + $c->stash->{hardcopyThemesAvailable} = $hardcopyThemesAvailable; $c->{prettyProblemNumber} = $c->{problemID} // ''; $c->{set} = $c->db->getGlobalSet($c->{setID}) if $c->{setID}; diff --git a/templates/ContentGenerator/Hardcopy/form.html.ep b/templates/ContentGenerator/Hardcopy/form.html.ep index 3abf00d416..ce42ad58dc 100644 --- a/templates/ContentGenerator/Hardcopy/form.html.ep +++ b/templates/ContentGenerator/Hardcopy/form.html.ep @@ -150,9 +150,9 @@

<%= maketext('Hardcopy Theme:') %> - % if (@{ $ce->{hardcopyThemes} } <= 3) { + % if (@{ $hardcopyThemesAvailable } <= 3) {
- % for (@{ $ce->{hardcopyThemes} }) { + % for (@{ $hardcopyThemesAvailable }) {