From d4301f3b5c89b189686c28f343c361189f14bf60 Mon Sep 17 00:00:00 2001
From: csangwin <C.J.Sangwin@ed.ac.uk>
Date: Sun, 10 Dec 2023 18:07:52 +0000
Subject: [PATCH] Update the docs (mostly spell checking)

---
 doc/en/Authoring/Advanced_JSXGraph.md         | 12 +--
 doc/en/Authoring/Answer_Tests/Calculus.md     |  8 +-
 doc/en/Authoring/Answer_Tests/Equivalence.md  | 10 +--
 doc/en/Authoring/Answer_Tests/Rule_based.md   | 20 ++---
 doc/en/Authoring/Answer_Tests/String.md       |  2 +-
 doc/en/Authoring/Answer_Tests/index.md        |  2 +-
 doc/en/Authoring/Authoring_quick_start.md     |  2 +-
 doc/en/Authoring/CASText.md                   | 12 ++-
 doc/en/Authoring/Equivalence_reasoning.md     | 10 +--
 doc/en/Authoring/Error_trapping.md            |  4 +-
 doc/en/Authoring/Errors.md                    | 51 +++++------
 doc/en/Authoring/Future_proof.md              | 10 +--
 doc/en/Authoring/Inclusions.md                | 43 ++++------
 doc/en/Authoring/Inputs.md                    | 84 +++++++++----------
 doc/en/Authoring/JSXGraph.md                  | 68 +++++++--------
 doc/en/Authoring/Multiple_choice_questions.md | 76 ++++++++---------
 doc/en/Authoring/Notes_about_performance.md   |  8 +-
 doc/en/Authoring/Parsons.md                   | 16 ++--
 doc/en/Authoring/Potential_response_trees.md  | 24 +++---
 .../Question_blocks/Conditional_blocks.md     |  2 +-
 .../Question_blocks/Dynamic_blocks.md         | 11 +--
 .../Question_blocks/Static_blocks.md          |  4 +-
 .../Question_blocks/System_blocks.md          |  4 +-
 doc/en/Authoring/Serving_out_data.md          |  6 +-
 doc/en/Authoring/Tables.md                    |  6 +-
 doc/en/Authoring/Testing.md                   |  4 +-
 doc/en/Authoring/Workflow.md                  |  1 -
 doc/en/CAS/Buggy_rules.md                     |  6 +-
 doc/en/CAS/Complex_numbers.md                 | 10 +--
 doc/en/CAS/Matrix.md                          |  6 +-
 doc/en/CAS/Maxima.md                          | 10 +--
 doc/en/CAS/Numbers.md                         | 18 ++--
 doc/en/CAS/Permutations.md                    |  6 +-
 doc/en/CAS/Predicate_functions.md             |  4 +-
 doc/en/CAS/Random.md                          |  4 +-
 doc/en/CAS/Real_Intervals.md                  |  4 +-
 doc/en/CAS/STACK-Maxima_sandbox.md            | 14 ++--
 doc/en/CAS/Simplification.md                  | 20 ++---
 doc/en/CAS/Validator.md                       |  4 +-
 doc/en/CAS/index.md                           |  2 +-
 doc/en/Developer/Development_track.md         | 20 ++---
 doc/en/Installation/Release_notes_4_4_x.md    |  4 +-
 doc/en/Installation/Testing_installation.md   | 30 +++----
 doc/en/Installation/index.md                  | 28 +++----
 doc/en/Maintaining/index.md                   |  8 +-
 doc/en/Moodle/Import_Export.md                | 10 +--
 doc/en/Moodle/Semi-automatic_Marking.md       |  4 +-
 doc/en/Moodle/index.md                        |  2 +-
 doc/en/Plots/Plots.md                         |  6 +-
 doc/en/Proof/Proof_CAS_library.md             |  2 +-
 doc/en/Proof/Proof_assessment.md              |  2 -
 doc/en/Proof/index.md                         |  8 +-
 doc/en/Students/FAQ.md                        |  4 +-
 doc/en/Topics/Differential_equations.md       | 16 ++--
 doc/en/Topics/GeoGebra.md                     |  6 +-
 doc/en/Topics/Levenshtein_distance.md         | 16 ++--
 doc/en/Topics/Parsons.md                      |  8 +-
 doc/en/Topics/Propositional_Logic.md          | 14 ++--
 doc/en/Topics/Unsorted_multi_input.md         |  6 +-
 doc/en/Topics/index.md                        |  4 +-
 60 files changed, 384 insertions(+), 422 deletions(-)

diff --git a/doc/en/Authoring/Advanced_JSXGraph.md b/doc/en/Authoring/Advanced_JSXGraph.md
index d80b983d5..e3d7c222b 100644
--- a/doc/en/Authoring/Advanced_JSXGraph.md
+++ b/doc/en/Authoring/Advanced_JSXGraph.md
@@ -1,12 +1,12 @@
 # Advanced JSXGraph: `stack_jxg.custom_bind`
 
-As stated in the general [JSXGraph-block docs](JSXGraph.md#manual_binding) binding together 
+As stated in the general [JSXGraph-block docs](JSXGraph.md#manual_binding) binding together
 STACK inputs and the state of the graph consists of three important things:
 
  1. We need to turn the state we wish to store into a string when it needs to be stored.
  2. We need to be able to restore the state from a string when need be, typically on page
     load or during two-way binding style usage.
- 3. We need to know when those things need to happen, i.e. what interractions with the graph
+ 3. We need to know when those things need to happen, i.e. what interactions with the graph
     trigger the first point and when to trigger the second.
 
 As this is almost always the same for all bindings the `stack_jxg` library provides a general
@@ -38,7 +38,7 @@ There are things that may not be obvious, here are some that are worth noting:
     that is enough to restore it, but the serialisation could still contain various angles
     or other helpful details in addition to those points so that you do not need to calculate
     them in Maxima.
- 2. The countter point to that is that you should never trust anything coming from
+ 2. The counter point to that is that you should never trust anything coming from
     the browser and nothing grading related should be calculated in the browser. However,
     it is pretty rare to see a student modifying the serialised state stored in the input
     so that it would contain wrong grading details, so do what feels natural. What is likely
@@ -76,7 +76,7 @@ The graph will not be directed and we will sort the edge listing for ease of use
 1-based indexing in the edge listing, and do some padding to keep our JavaScript side indexing of
 points 1-based as well.
 
-For user interface we will use a logic where dragging nodes into a particular area will 
+For user interface we will use a logic where dragging nodes into a particular area will
 connect/disconnect them from other nodes within that area. There will also be an area from which
 one can drag new nodes out of or into which one can drop extra nodes for destruction.
 
@@ -286,7 +286,7 @@ const deserialiser = (value) => {
 	board.update();
 };
 
-/* Then lets add a magical point for creating new nodes. If one drags it outside 
+/* Then lets add a magical point for creating new nodes. If one drags it outside
    the circle it will create a new node at that place before returning back. */
 const magicPoint = board.create('point', [source.center.X(), source.center.Y()], {name: 'Place me to create a new node.', size: 0.2, sizeUnit: 'user'});
 magicPoint.on('up', () => {
@@ -324,7 +324,7 @@ At 1. the serialiser is rather simple, if yours is not consider whether the way
 state is clear enough. Typically, well constructed state is easy to serialise.
 
 At 2. the key thing to note is that when we create new elements that need to be bound we need
-to register them, unregistering is not possible and one should probably not care about that, as
+to register them, un-registering is not possible and one should probably not care about that, as
 extra registered items, while taking room and time during evaluation of logic are not that
 common and will be dropped during page refresh. Typically, users do not do so many actions that
 the lag would be noticeable.
diff --git a/doc/en/Authoring/Answer_Tests/Calculus.md b/doc/en/Authoring/Answer_Tests/Calculus.md
index 421b2e374..2b1af8a08 100644
--- a/doc/en/Authoring/Answer_Tests/Calculus.md
+++ b/doc/en/Authoring/Answer_Tests/Calculus.md
@@ -18,7 +18,7 @@ In particular, the test assumes that the constant of integration is expressed in
 
 The Int test has various additional options.
 
-The question author must supply these options in the form of a list `[var, opt1, ...]`.  The first argument of this list must be the variable with respect to which integration is taking place.  
+The question author must supply these options in the form of a list `[var, opt1, ...]`.  The first argument of this list must be the variable with respect to which integration is taking place.
 
 If one of the `opt?` is exactly the token `NOCONST` then the test will condone a lack of constant of integration.  That is, if a student has missed off a constant of integration, or the answers differ by a numerical constant, then full marks will be awarded.  Weird constants (e.g. \(+c^2\)) will still be flagged up.
 
@@ -31,7 +31,7 @@ In many cases simply differentiating the teacher's answer is fine, in which case
 
 The test cannot cope with some situations.  Please contact the developers when you find some of these.  This test is already rather overloaded, so please don't expect every request to be accommodated!
 
-This test, in particular, has a lot of test cases which really document what the test does in detail.  
+This test, in particular, has a lot of test cases which really document what the test does in detail.
 
 The issue of \( \int \frac{1}{x} dx = \log(x)+c\) vs  \( \int \frac{1}{x} dx = \log(|x|)+c\) is a particular challenge. What mark would you give a student who integrated
 \[ \int \frac{1}{x} dx = \log(k\times abs(x))?\]
@@ -47,6 +47,6 @@ Now, the following are rejected as incorrect, as the studnet should have used \(
 
 Note that STACK sets the value of Maxima's `logabs:true`, which is not the default in Maxima.  This has the effect of adding the absolute value funtion when `integrate` is used.
 
-In the case of partial  fractions where there are more than one term of the form \(\log(x-a)\) then 
-we insist the student is at least consistent.  If the teacher has *any*  \(\log(|x-a|)\) then the student must use \(|...|\) in *all* of them.  If the teacher has no \(\log(|x-a|)\) (i.e. just things like \(\log(x-a)\)) then the 
+In the case of partial  fractions where there are more than one term of the form \(\log(x-a)\) then
+we insist the student is at least consistent.  If the teacher has *any*  \(\log(|x-a|)\) then the student must use \(|...|\) in *all* of them.  If the teacher has no \(\log(|x-a|)\) (i.e. just things like \(\log(x-a)\)) then the
 student must have all or none. 
\ No newline at end of file
diff --git a/doc/en/Authoring/Answer_Tests/Equivalence.md b/doc/en/Authoring/Answer_Tests/Equivalence.md
index 2d59635c5..20ce1c43f 100644
--- a/doc/en/Authoring/Answer_Tests/Equivalence.md
+++ b/doc/en/Authoring/Answer_Tests/Equivalence.md
@@ -10,9 +10,9 @@ This list is in approximate order of the size of the equivalence classes from mo
 
 | Test                                              | Description (see below for more details)
 | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------
-| CasEqual                                          | Are the [parse trees](../Trees.md) of the two expressions equal?  
-| [EqualComAss](Rule_based.md)                      | Are they equal up to commutativity and associativity of addition and multiplication, together with their inverses minus and division? 
-| [EqualComAssRules](Rule_based.md)                 | Are they equal up to commutativity, associativity and with optional rules such as \(0\times x \rightarrow 0\)? 
+| CasEqual                                          | Are the [parse trees](../Trees.md) of the two expressions equal?
+| [EqualComAss](Rule_based.md)                      | Are they equal up to commutativity and associativity of addition and multiplication, together with their inverses minus and division?
+| [EqualComAssRules](Rule_based.md)                 | Are they equal up to commutativity, associativity and with optional rules such as \(0\times x \rightarrow 0\)?
 | AlgEquivNouns                                     | Are they _algebraically equivalent_, preserving noun forms of operators, e.g. `diff`?
 | AlgEquiv                                          | Are they _algebraically equivalent_?
 | SubstEquiv                                        | Can we find a substitution of the variables of \(ex_2\) into \(ex_1\) which renders \(ex_1\) algebraically equivalent to \(ex_2\)?
@@ -36,7 +36,7 @@ This test will work with a variety of [types of object](../../CAS/Maxima.md#Type
 
 Note: exactly what it does depends on what objects are given to it.  In particular the pseudo code above only applies to expressions.  We cannot subtract one list or set from another, so we have to use other tests.
 
-For sets, the CAS tries to write the expression in a canonical form.  It then compares the string representations these forms to remove duplicate elements and compare sets.  This is subtly different from trying to simplify the difference of two expressions to zero.  For example, imagine we have \(\{(x-a)^{6000}\}\) and \(\{(a-x)^{6000}\}\).  One canonical form is to expand out both sides.  While this work in principal, in practice this is much too slow for assessment. 
+For sets, the CAS tries to write the expression in a canonical form.  It then compares the string representations these forms to remove duplicate elements and compare sets.  This is subtly different from trying to simplify the difference of two expressions to zero.  For example, imagine we have \(\{(x-a)^{6000}\}\) and \(\{(a-x)^{6000}\}\).  One canonical form is to expand out both sides.  While this work in principal, in practice this is much too slow for assessment.
 
 Currently we do check multiplicity of roots, so that \( (x-2)^2=0\) and \( x=2\) are not considered to be equivalent.  Similarly \(a^3b^3=0\) is not \(a=0 \mbox{ or } b=0\).  This is a long-standing issue and we would need a separate test to ignore multiplicity of roots.
 
@@ -81,7 +81,7 @@ The CAS returns the result of the simple Maxima command
 
 There is no explicit simplification here (unlike AlgEquiv).
 This test always assumes [simplification](../../CAS/Simplification.md) is off, i.e. `simp:false`, regardless of any question settings.  If this is too strict, use `ev(ex,simp)` in the arguments to simplify them explicitly first.
-When simplification is off this test effectively tests whether the parse trees are identical. 
+When simplification is off this test effectively tests whether the parse trees are identical.
 
 Please note, the behaviour of this test relies on the internal representation of expressions by Maxima, rather than an explicit mathematical property such as "equivalence".  Explicit properties should be tested in preference to using this test!
 
diff --git a/doc/en/Authoring/Answer_Tests/Rule_based.md b/doc/en/Authoring/Answer_Tests/Rule_based.md
index 2e57ef252..b9e7ff61f 100644
--- a/doc/en/Authoring/Answer_Tests/Rule_based.md
+++ b/doc/en/Authoring/Answer_Tests/Rule_based.md
@@ -10,20 +10,20 @@ For example \[a+b=b+a\mbox{,}\] but \[x+x\neq 2x\mbox{.}\] This is very useful i
 
 This is a particularly useful test for checking that an answer is written in a particular form, e.g. "simplified".
 
-Notes 
+Notes
 
 1. This test does not include laws of indices, so \(x\times x \neq x^2\). Since we are dealing only with nouns \(-\times -\) does not simplify to \(1\). E.g. \(-x\times -x \neq x\times x \neq x^2\).  This also means that \(\sqrt{x}\) is not considered to be equivalent to \(x^{\frac{1}{2}}\) under this test.  In many situations this notation is taken to mean the same thing, but internally in Maxima they are represented by different functions and are not converted to a canonical form by the test.
 2. By design, addition commutes with subtraction, so \( -1+2\equiv 2-1\) and multiplication commutes with division, so \( (ab)/c\equiv a(b/c) \).
 3. By design \(-1/4x \neq -x/4\) since we do not have the rule \( 1\times x \rightarrow x\).  To establish this equivalence we would need a different answer test.
 4. This test can also be used to establish \(\{4,4\} \neq \{4\}\), but \(\{1,2\} = \{2,1\}\) since the arguments of the set constructor function are commutative.  Sets are not associative, so \(\{1,2\} \neq \{\{1\},2\}\).  (See Maxima's `flatten` command.)
-5. Simplification is automatically switched off when this test is applied, otherwise it makes no sense. 
+5. Simplification is automatically switched off when this test is applied, otherwise it makes no sense.
 
 
 ### Unary minus and division ###
 
 In order to understand how the tests work it is essential to understand how we represent unary minus and division internally.
 
-Without simplification, Maxima has a unary minus function.  Litterally `minus(x)`.  This is transformed into `UNARY_MINUS nounmul ex`  The use of multiplication here allows `-` to commute with other multiplication, so we can spot things like \(-x \times -y = --xy\) using associativity and commutativity.
+Without simplification, Maxima has a unary minus function:  literally `minus(x)`.  This is transformed into `UNARY_MINUS nounmul ex`  The use of multiplication here allows `-` to commute with other multiplication, so we can spot things like \(-x \times -y = --xy\) using associativity and commutativity.
 
 Similarly, we replace division \(a/b\) with `a nounmul UNARY_RECIP(b)`.  This means that `UNARY_RECIP(b)` is not automatically the same as `1 nounmul UNARY_RECIP(b)`, without an additional rule.
 
@@ -31,7 +31,7 @@ Similarly, we replace division \(a/b\) with `a nounmul UNARY_RECIP(b)`.  This me
 
 This is an advanced test.
 
-This test allows question authors to create equivalence classes based on equality up to associativity and commutativity with the addition of optional rules. For example, the teacher can include the identity operations of addition and multiplication: \(0+ x\rightarrow x\) and \(1\times x\rightarrow x\).  This makes it much easier to establish things like \(0-1\times i\) is equivalent to \(-i\).  However, more general integer arithmatic is still not automatically included so \(2\times 3 \neq 6\).
+This test allows question authors to create equivalence classes based on equality up to associativity and commutativity with the addition of optional rules. For example, the teacher can include the identity operations of addition and multiplication: \(0+ x\rightarrow x\) and \(1\times x\rightarrow x\).  This makes it much easier to establish things like \(0-1\times i\) is equivalent to \(-i\).  However, more general integer arithmetic is still not automatically included so \(2\times 3 \neq 6\).
 
 This test always assumes associativity and commutativity of addition and multiplication.  Essentially this test extends the `EqualComAss` test by adding in additional rules. Without assumptions of commutativity and associativity we would need all sorts of additional rules, such as \(x+0 \rightarrow x\), since without commutativity this would not be captured by the rule `zeroAdd`, i.e. \(0+x \rightarrow x\).  Furthermore, the way `EqualComAss` deals with unary minus and division make associativity and commutativity difficult to add in their pure form.
 
@@ -75,16 +75,16 @@ The teacher must supply an option consisting of a list of the following rule nam
 
 The rule `negOrd` deserves comment.  Ultimately we only compare parse trees exactly, and so we need to order terms in sums and products (commutativity).
 However \(y-x\) is never ordered as \(-x+y\).  Furthermore, \(-(x-y) \neq -x+y\).  We need to factor out the unary minus and ensure that the coefficient of the leading term is not negative.
-Factoring out is better than distributing here, since in a produce such as \(-(x-y)(x-z)\) it is not clear which term in the product the inital minus sign will end up in.
+Factoring out is better than distributing here, since in a produce such as \(-(x-y)(x-z)\) it is not clear which term in the product the initial minus sign will end up in.
 Since `negOrd` is a factor command, it is incompatible with `negDist`.
 
-For convenience sets of rules can be specificed.  E.g. you can use the name `ID_TRANS` in place of the list `[zeroAdd,zeroMul,oneMul,oneDiv,onePow,idPow,zeroPow,zPow]` to include all of the basic identity operators.
+For convenience sets of rules can be specified.  E.g. you can use the name `ID_TRANS` in place of the list `[zeroAdd,zeroMul,oneMul,oneDiv,onePow,idPow,zeroPow,zPow]` to include all of the basic identity operators.
 
 If you want to remove tests from a list you can use code such as `delete(zeroAdd, ID_TRANS)`.
 
-The test takes the student's answer and teacher's answer and repeatedly applies the rules in turn until the expressions remain the same.  The rules are designed to always shorten the expression, so the process is guranteed to terminate.  Once the expression is written in final form, the test compares the two expression trees.
+The test takes the student's answer and teacher's answer and repeatedly applies the rules in turn until the expressions remain the same.  The rules are designed to always shorten the expression, so the process is guaranteed to terminate.  Once the expression is written in final form, the test compares the two expression trees.
 
-Note that we do not gurantee the simplification is mathematically correct!  E.g. if you are unlucky enough to try the rule `zeroPow` on the expression `0^(1-1)` then since `1-1` is not equal to zero (taken literally) then the rule applies and you have failed to spot a potential `0^0` error.
+Note that we do not guarantee the simplification is mathematically correct!  E.g. if you are unlucky enough to try the rule `zeroPow` on the expression `0^(1-1)` then since `1-1` is not equal to zero (taken literally) then the rule applies and you have failed to spot a potential `0^0` error.
 
 If you add the rule `testdebug` then you will see both expressions in the answer note.  This is useful for debugging, but would clutter up things in a production setting.
 
@@ -101,9 +101,9 @@ Note, this test always assumes commutativity so you can't (currently) enforce th
 
 ## Developer notes ##
 
-This functionality was introduced in April 2021.  It is essential that the rules, and any combination of the rules, can only proceed in a single direction and that no infinite loops are created.  So, `intAdd` is fine because adding together two integers will make an expression _simpler_ which in this case is shorter.  For this reason we do not have expanding out (i.e. distribution) rules in the above set, and no rules of indices (which readily lead to mathemtical errors).  Use Maxima's simplifier if you want to include such rules.
+This functionality was introduced in April 2021.  It is essential that the rules, and any combination of the rules, can only proceed in a single direction and that no infinite loops are created.  So, `intAdd` is fine because adding together two integers will make an expression _simpler_ which in this case is shorter.  For this reason we do not have expanding out (i.e. distribution) rules in the above set, and no rules of indices (which readily lead to mathematical errors).  Use Maxima's simplifier if you want to include such rules.
 
-The rules names are Maxima functions, but they assume `simp:false` and that the expression has noun forms e.g. `nounadd` instead of `+`.  You can use `equals_commute_prepare(ex)` to change an expression into this noun form.  The goal of this code is to create reliable equivalence classes of expressions, not perform algebraic manipulation as we traditionally know it. In particular the way unary minus is transformed into multiplication with a special tag `UNARY_MINUS` is likely to cause confusion to students if an expression is manipulated using these rules and then shown to a student.  The transoformation is designed to go in one direction only, and we do not support displaying the resulting manipulated expressions in traditional form.
+The rules names are Maxima functions, but they assume `simp:false` and that the expression has noun forms e.g. `nounadd` instead of `+`.  You can use `equals_commute_prepare(ex)` to change an expression into this noun form.  The goal of this code is to create reliable equivalence classes of expressions, not perform algebraic manipulation as we traditionally know it. In particular the way unary minus is transformed into multiplication with a special tag `UNARY_MINUS` is likely to cause confusion to students if an expression is manipulated using these rules and then shown to a student.  The transformation is designed to go in one direction only, and we do not support displaying the resulting manipulated expressions in traditional form.
 
 __As of May 2023, these rules are not intended as an end-user simplifier and we do not currently support user-defined rules (sorry!).__
 
diff --git a/doc/en/Authoring/Answer_Tests/String.md b/doc/en/Authoring/Answer_Tests/String.md
index e7c4bf311..8b30d6f69 100644
--- a/doc/en/Authoring/Answer_Tests/String.md
+++ b/doc/en/Authoring/Answer_Tests/String.md
@@ -22,7 +22,7 @@ This test uses Maxima's `regex_match` function.
 * The first argument should be the string, and the second argument should be the pattern to match.
 * It yields true if the pattern is matched anywhere within the student answer and false otherwise. Testing for full equality of the answer string can be achieved via regex anchoring by use of `^` or `$`.
 * Don't forget to escape within the pattern strings as needed. Note that there is a function `string_to_regex()` that will handle escaping of characters that would otherwise have meaning in the pattern. Also remember that you need to escape the backslashes like normal in Maxima-strings.  That is to say, if you want to use `\s` in a pattern you need to double up the backslashes. For example `"(Alice|Bob)\\s+went\\s+to\\s+the\\s+(bank|market)"`.
-* One can read more about the patterns posible from [here](http://ds26gte.github.io/pregexp/index.html). Case-insensitivity may be something worth noting there.
+* One can read more about the patterns possible from [here](http://ds26gte.github.io/pregexp/index.html). Case-insensitivity may be something worth noting there.
 
 For example, write a STACK question with the following question variables.
 
diff --git a/doc/en/Authoring/Answer_Tests/index.md b/doc/en/Authoring/Answer_Tests/index.md
index 47b4ace7e..0c8f9117e 100644
--- a/doc/en/Authoring/Answer_Tests/index.md
+++ b/doc/en/Authoring/Answer_Tests/index.md
@@ -76,7 +76,7 @@ Documentation is grouped as follows.
   * [EquivFirst](../../CAS/Equivalence_reasoning.md)
   * [PropLogic](../../Topics/Propositional_Logic.md)
 
-## Pre-pocessing students' answers ##
+## Pre-processing students' answers ##
 
 You can apply functions before applying the tests using the feedback variables.  For example, to ignore case sensitivity you can apply the [Maxima commands defined by STACK](../../CAS/Maxima.md#Maxima_commands_defined_by_STACK) `exdowncase(ex)` to the arguments, before you apply one of the other answer tests. However, some tests really require the raw student's input.  E.g. the numerical decimal place test really requires the name of an input as the `SAns` field.  If you manipulate an input, you may end up dropping trailing zeros and ruining the number of decimal places in the expression.  STACK will warn you if you need to use the name of an input.
 
diff --git a/doc/en/Authoring/Authoring_quick_start.md b/doc/en/Authoring/Authoring_quick_start.md
index 0921664e4..8612cfd20 100644
--- a/doc/en/Authoring/Authoring_quick_start.md
+++ b/doc/en/Authoring/Authoring_quick_start.md
@@ -2,4 +2,4 @@
 
 STACK provides a structured [author quick start guide](../AbInitio/Authoring_quick_start_1.md) for new users.
 
-This guide has been used by many people, but we accept that authoring questions is a complex process.  Developing expertise in authoring STACK questions will require some commitement.
+This guide has been used by many people, but we accept that authoring questions is a complex process.  Developing expertise in authoring STACK questions will require some commitment.
diff --git a/doc/en/Authoring/CASText.md b/doc/en/Authoring/CASText.md
index 8c6f58c15..93bebebcf 100644
--- a/doc/en/Authoring/CASText.md
+++ b/doc/en/Authoring/CASText.md
@@ -42,7 +42,7 @@ To control whether or not the CAS expressions are simplified, see the details ab
 
 The question text what the student actually sees.  This was called "question text" in previous versions.
 
-It is a slightly modified form of CAS text.  To allow a student to answer a question you must include an [inputs](Inputs.md) in the question text. For example, students need a box into which their answer will be put.
+It is a slightly modified form of CAStext.  To allow a student to answer a question you must include an [inputs](Inputs.md) in the question text. For example, students need a box into which their answer will be put.
 
 To place an [input](Inputs.md) into the question enclose the name of the [Maxima](../CAS/Maxima.md) variable to which the student's answer is assigned between inside the following tag.  If the student's answer is going to be assigned to the variable `ans1` then use the tag `[[input:ans1]]`.  You will also be required to place a corresponding tag to indicate the position of any validation feedback (whether or not this is shown to the student): `[[validation:ans1]]`.  You can use any legitimate variable name.
 
@@ -50,7 +50,7 @@ To place an [input](Inputs.md) into the question enclose the name of the [Maxima
 * When the student answers, this variable name is available to each [potential response trees](Potential_response_trees.md).
 * Inputs are created and deleted by adding appropriate tags to the question text.  Therefore, beware if you delete the tags as this will also delete the input from the question.
 
-To place another potential response tree in the question just choose a sensible name and add in a tag `[[feedback:prt1]]`.  
+To place another potential response tree in the question just choose a sensible name and add in a tag `[[feedback:prt1]]`.
 
 * These tags are replaced by appropriate feedback as necessary.  Note, if you add the feedback to the question text this will always be shown by the STACK question, regardless of the quiz settings.  You may prefer to place the tags in the "specific feedback" block of the editing form.  Availability of the specific feedback is controlled by the Moodle quiz settings.  There is some compromise here between the ability to position the feedback tags anywhere in the question text (e.g. next to a particular input) and control over when it is shown.  This is most difficult in questions with many parts.  For a single part question we recommend you use the specific feedback block.
 * Tags can be moved anywhere within the question text.
@@ -63,15 +63,13 @@ To place another potential response tree in the question just choose a sensible
 General feedback (called "worked solution" in previous versions) is shown to the student after they have attempted the question. Unlike feedback, which depends on the response the student gave, the same general feedback text is shown to all students.
 
 The general feedback may depend on any question variables, but may _not_ depend on any of the inputs.
-While this design decision is restrictive, it is a deliberate separation of feedback
-which should be done via potential response trees, from a model solution to this
-problem which can be written before a question is deployed.
+While this design decision is restrictive, it is a deliberate separation of feedback which should be done via potential response trees, from a model solution to this problem which can be written before a question is deployed.
 
 ## CASText and currency {#currency}
 
 It is common to want to use the dollar sign for currency.  However, this conflicts with the use of the dollar sign for delimiters for mathematics.  For this reason we discourage the use of dollars to delimit mathematics in STACK.
 
-* If you are using dollars for currency then you must protect them with a backslash, i.e. `\$`, otherwise the CASText validation will fail.
+If you are using dollars for currency then you must protect them with a backslash, i.e. `\$`, otherwise the CASText validation will fail.
 
 ## Facts ##
 
@@ -87,7 +85,7 @@ HTML and LaTeX are needed for authoring STACK questions, and some basic referenc
 
 ## CASText generating functions ##
 
-If a CASText area is to include several copies of repeatative content, for instance several versions of some text (or a SVG graphic) containing 
+If a CASText area is to include several copies of repetitive content, for instance several versions of some text (or a SVG graphic) containing
 different parameters, it is possible to define a CASText generating function within the Question variables using the STACK function `castext`.
 
 For example, within the [Question variables](Variables.md) section, define
diff --git a/doc/en/Authoring/Equivalence_reasoning.md b/doc/en/Authoring/Equivalence_reasoning.md
index e59ecdcb1..9eaf1eccd 100644
--- a/doc/en/Authoring/Equivalence_reasoning.md
+++ b/doc/en/Authoring/Equivalence_reasoning.md
@@ -9,7 +9,7 @@ The student's response to this question will allow us to test their knowledge an
 1. Expanding brackets
 2. Simplifying by collecting like terms
 
-Therefore we need them to show their working. 
+Therefore we need them to show their working.
 
 ## Minimal working question ##
 
@@ -36,7 +36,7 @@ The variable `ta` is a list containing each step we are expecting our students t
 
 Notes:
 
-* We use the CAS functions `expand()` and `ev(...,simp)` to simply the output of `expand()`, to determine the model answer. 
+* We use the CAS functions `expand()` and `ev(...,simp)` to simply the output of `expand()`, to determine the model answer.
 * The special function `stackeq` is replaced by unary equals.  Maxima expects equality to be an infix \(a=b\) not unary prefix \(=b\), so STACK needs this special operator.  Students using the input area can just start a line with \(=\), but teachers cannot!
 
 In this context the teacher's answer and the student's answer is a list.  The whole answer is a single object, which we assess.
@@ -66,7 +66,7 @@ This ensures a student's response will be invalid if they don't have the correct
 
 ### Setting the potential response tree ###
 
-As a minimal potential response tree have one node, with 
+As a minimal potential response tree have one node, with
 
     Answer test = EquivFirst
     SAns = ans1
@@ -115,9 +115,7 @@ If you really want the term order as well, as in, \(x^{3}+6x^{2}+12x+8\) then yo
 
 At this point, any expressions which are equivalent are considered to be a legitimate step.
 
-Clearly this is not entirely satisfactory.
-At this point in the development there is no concept of "a step" and indeed this appears to be very hard to define.
-In the future we will develop better tools for checking "step size", and any contributions in this direction are welcome.
+Clearly this is not entirely satisfactory. At this point in the development there is no concept of "a step" and indeed this appears to be very hard to define. In the future we will develop better tools for checking "step size", and any contributions in this direction are welcome.
 
 Teachers can check the students answer is long enough or not too long by looking at `length(ta)`.
 
diff --git a/doc/en/Authoring/Error_trapping.md b/doc/en/Authoring/Error_trapping.md
index f33794574..9fd07fff7 100644
--- a/doc/en/Authoring/Error_trapping.md
+++ b/doc/en/Authoring/Error_trapping.md
@@ -2,7 +2,7 @@
 
 How to I trap errors generated from a student's answer?
 
-Errors are generated for a number of reasons.  Mostly, they are important and should not be ignored!  Normally, students should not be penalised if a question "does not work" because the PRT generated an error.  Any runtime error during traversing a PRT will cause an error.  This error will stop further exectution of the tree, and students will see a runtime error message.  This will be flagged in the response summary as `[RUNTIME_ERROR]`.
+Errors are generated for a number of reasons.  Mostly, they are important and should not be ignored!  Normally, students should not be penalised if a question "does not work" because the PRT generated an error.  Any runtime error during traversing a PRT will cause an error.  This error will stop further execution of the tree, and students will see a runtime error message.  This will be flagged in the response summary as `[RUNTIME_ERROR]`.
 
 
 A student's answer can generate mathematical errors for a number of reasons, but the most common is evaluating a function outside its mathematical domain.  Common elementary examples are
@@ -18,7 +18,7 @@ If one of the feedback variables throws an error then this will not stop the PRT
 
     sa1:errcatch(tan(ans1));
 
-If `ans1:%pi/2` then `sa1` will be the empty list `[]`.  Otherwise, `sa1` will be the list containg the result, and you can use `first(sa1)` in a PRT.
+If `ans1:%pi/2` then `sa1` will be the empty list `[]`.  Otherwise, `sa1` will be the list containing the result, and you can use `first(sa1)` in a PRT.
 
 To trap a runtime error, or create a guard clause, you do need extra node in your tree (e.g. is `sa1` empty) or an `if` statement in your feedback variables.  The default is to show errors, so if you choose to test for and condone errors you need extra clauses.
 
diff --git a/doc/en/Authoring/Errors.md b/doc/en/Authoring/Errors.md
index b3d8871dc..dc4ad18bb 100644
--- a/doc/en/Authoring/Errors.md
+++ b/doc/en/Authoring/Errors.md
@@ -1,7 +1,7 @@
 # Authoring validation errors
 
 This document aims to explain certain errors that may appear during authoring, specifically during
-validation/saving of a question.  We are constantly improving the error trapping for question 
+validation/saving of a question.  We are constantly improving the error trapping for question
 authors and so some of these errors might be new and appear during upgrades, and break, previously functional materials.
 
 In some cases we have good reasons for now preventing actions which may have been permitted in the past.
@@ -19,10 +19,10 @@ Summary of advice.
 
 Some functions affecting the underlying system are forbidden to protect
 the environment, others are forbidden due to excessive load, and finally some
-have been disabled due to the way they return their values. Likewise, some 
+have been disabled due to the way they return their values. Likewise, some
 variables/constants representing the state of the underlying system have
-been either marked as forbbiden to access or to modify. Use other names
-if this was just a collision of identifiers, otherwise this is just the way 
+been either marked as forbidden to access or to modify. Use other names
+if this was just a collision of identifiers, otherwise this is just the way
 it is.
 
 ## Redefining internal-functions
@@ -39,13 +39,9 @@ We suggest you do not attempt to redefine function names or constants which are
 
 ## Substitutions unclear or otherwise
 
-Should you do substitutions of values in your code and the target of
-the substitution is an identifier that is later used as a function-name,
-things may become difficult. Avoid using the same name for functions and variables. 
-Also if you use complex means to construct the substitutions themselves the system may need to assume that all
-possible identifiers in the expression that the substitutions are applied
-to are being targetted by unknown values, this can be avoided by avoiding
-complex construction of the substs itself.
+Should you do substitutions of values in your code and the target of the substitution is an identifier that is later used as a function-name,
+things may become difficult. Avoid using the same name for functions and variables.
+Also if you use complex means to construct the substitutions themselves the system may need to assume that all possible identifiers in the expression that the substitutions are applied to are being targeted by unknown values, this can be avoided by avoiding complex construction of the substitution itself.
 
 Note, these issues are now much rarer after the security system changed in 4.4. Yo should not even see these errors with the new system.
 
@@ -92,12 +88,7 @@ TAns12 : subst([%k2=A,%k1=B],solution);
 
 ## Use of the students answer
 
-Since 4.3 you have been forbidden from writing to the variable storing 
-the students answer, feel free to simply store whatever you wanted to 
-store in any other valid variable. You are now also forbidden from using
-the students input directly as a function-name, if you need to do so 
-rewrite the logic as a "switch", unfortunately this also applies to MCQ
-inputs:
+Since 4.3 you have been forbidden from writing to the variable storing the students answer, feel free to simply store whatever you wanted to store in any other valid variable. You are now also forbidden from using the students input directly as a function-name, if you need to do so rewrite the logic as a "switch", unfortunately this also applies to MCQ inputs:
 
 ```
 /* Not like this. */
@@ -114,11 +105,7 @@ else if(ans1=sin) then
 
 ## `ev` in 4.4
 
-The new security model of STACK 4.4 modifies the order of execution in such 
-a way that `ev` does not quite match the behaviour of `ev` in Maxima. For 
-most use cases you will not notice this but there are situations where
-things won't work as expected. In general, these are the situations currently 
-known:
+The new security model of STACK 4.4 modifies the order of execution in such a way that `ev` does not quite match the behaviour of `ev` in Maxima. For most use cases you will not notice this but there are situations where things won't work as expected. In general, these are the situations currently known:
 
  1. Placing `expand` inside of `ev` and doing a substitution in the same `ev`:
  ```
@@ -132,8 +119,8 @@ known:
  ```
  2. Substitutions in general may happen too late if the target expression contains calls requiring security validation. The recommended method for dealing with this is to do the substitutions using `subst` or `at` and applying any evaluation related modifications with `ev` separately.
  3. Use of the `noeval` evaluation flag might not work, in general this flag is unlikely to be useful in the context of STACK and if you believe you need it look into nounification and other means of doing similar things.
- 
-In some cases, it is possible to simply add `eval` as an extra flag to 
+
+In some cases, it is possible to simply add `eval` as an extra flag to
 the `ev`-call, however this is only possible if all substitutions in the call are
 such that the LHS of the substitution is not present in the RHS.
 
@@ -147,27 +134,27 @@ tmp: ev(a+1,a=2);
 
 # Some recomendations
 
-The validation of certain things evaluates dependency graphs of 
+The validation of certain things evaluates dependency graphs of
 identifiers so if you can keep those graphs small things tend to work
 faster. To do so avoid redefining the same variable if at all possible
-and just create a new variable when needed, i.e. do not reuse some 
+and just create a new variable when needed, i.e. do not reuse some
 `tmp`-var for all the calculations, if you do then the graph of that
-variable will become quite large and that may slow things down. Many 
-small graphs tend to be faster to deal with than few large ones and 
+variable will become quite large and that may slow things down. Many
+small graphs tend to be faster to deal with than few large ones and
 a large graph may mean that features of node in the graph may block
 other nodes from doing certain things, e.g. being used as function
 identifiers.
 
 Likewise, avoid reusing same variable names for multiple different
 types of things in the question, i.e. if `A` is a matrix let it stay
-as such and don't turn it into a list or a function if you wish 
+as such and don't turn it into a list or a function if you wish
 the validation during saving and first execution after import/upgrade
 to be fast.
 
 If you are using `local()` to define local-scope variables always call
 it as the first thing in a `block` (if you use the list of identifiers
-logic then you should not use `local()` in the same block) or in a `lambda` 
-(after arguments). This allows the graph building to identify the point of 
-disconnection of the graphs and to separate the scopes. Calling `local` 
+logic then you should not use `local()` in the same block) or in a `lambda`
+(after arguments). This allows the graph building to identify the point of
+disconnection of the graphs and to separate the scopes. Calling `local`
 after any variables have been used will confuse the logic and we do not
 want to invest into dealign with that special case.
diff --git a/doc/en/Authoring/Future_proof.md b/doc/en/Authoring/Future_proof.md
index b6407cdb8..aab271fc0 100644
--- a/doc/en/Authoring/Future_proof.md
+++ b/doc/en/Authoring/Future_proof.md
@@ -1,6 +1,6 @@
 # Guidelines for ensuring that a question works in the future
 
-Creating a great STACK question takes effort and often people worry about how updating STACK or Moodle or other components running those questions might affect their questions. While there are no guarantees you can increase the ongoing reliability of your questions by taking the following things into account. 
+Creating a great STACK question takes effort and often people worry about how updating STACK or Moodle or other components running those questions might affect their questions. While there are no guarantees you can increase the ongoing reliability of your questions by taking the following things into account.
 
 In some parts of this document we mention "Abacus". The Abacus project is a STACK material sharing organisation that seeks to develop high-quality materials to be implemented following these guidelines. This document ends with additional guidelines adopted by Abacus.  This is both good practice, and will be relevant if you ever intend to join Abacus.
 
@@ -35,7 +35,7 @@ If your CASText document contains scripts like JSXGraph content definitions you
 
 __All external files/links are bad!__ If you have images or other documents related to the question they should be included in the question. Avoid embedded frames, applets and other interactive content. To test inclusion you should be able to export the question and import it to a freshly installed raw system on a computer not connected to the internet and those questions should work. *There is nothing wrong with internal files of any type, as long as they come with the question.* Use of the [include](Inclusions.md) feature from 4.4 is also a bad thing, but you can make it less bad if the included file is present on a public server and if it is versioned so that one can link to a version that never changes.
 
-STACK does provide the option for [inclusions](Inclusions.md) within questions.  If you regularly use `stack_inlude` in your questions please consider contributing your libraries to the STACK core code.  Contributing tested libraries is the best way to ensure longer term maintainance!
+STACK does provide the option for [inclusions](Inclusions.md) within questions.  If you regularly use `stack_inlude` in your questions please consider contributing your libraries to the STACK core code.  Contributing tested libraries is the best way to ensure longer term maintenance!
 
 ## Writing CAS code
 
@@ -66,7 +66,7 @@ Please note that the system administrator has access to a "bulk test" script whi
 
 There have been some changes, which have created broken questions between versions.
 
-* List instantiation in Maxima is now required by Maxima and writing to an uninstantiated list gives errors like 'ARRSTORE: use_fast_arrays=false; allocate a new property hash table'. Basically, this means that you cannot say `TAns[1]:x;` without first saying `TAns:[];`. So do not assume that Maxima knows you want to create a list by simply assigning to an index on an undefined variable.
+* List instantiation in Maxima is now required by Maxima and writing to an un-instantiated list gives errors like 'ARRSTORE: use_fast_arrays=false; allocate a new property hash table'. Basically, this means that you cannot say `TAns[1]:x;` without first saying `TAns:[];`. So do not assume that Maxima knows you want to create a list by simply assigning to an index on an undefined variable.
 * Maxima has its own `addrow` command, that differs from STACKs version. Please check any questions using `addrow`. Eventually, a conversion will be made that will switch the arguments of function calls in old questions using the old STACK version of that function but the change process will be long.
 
 
@@ -110,8 +110,8 @@ It is perfectly acceptable to place the PRT-feedback marker within the question
 
 ### CAS Code & input and PRT naming
 
-Abacus materials should aim to use English names for the CAS variables, inputs and PRTs to ease debugging by other members. Realistically, when generating new localisations for an existing question the variables should be renamed at the same time unless they are already in English. 
+Abacus materials should aim to use English names for the CAS variables, inputs and PRTs to ease debugging by other members. Realistically, when generating new localisations for an existing question the variables should be renamed at the same time unless they are already in English.
 
 If a variable name could cause confusion you should describe the variable in inline comments. You should use verbose internal variable names but not too verbose, try to aim for less than 10 characters. PascalCase/camelCase is the recommended way of dealing with multi word verbose names.
 
-Naming of PRTs is highly recommended, even `partA` and `partB` will be more descriptive names than `prt1` and `prt2`, naming of PRTs happens when you create them i.e. when you create that PRT-feedback marker.
\ No newline at end of file
+Naming of PRTs is highly recommended, even `partA` and `partB` will be more descriptive names than `prt1` and `prt2`, naming of PRTs happens when you create them i.e. when you create that PRT-feedback marker. 
\ No newline at end of file
diff --git a/doc/en/Authoring/Inclusions.md b/doc/en/Authoring/Inclusions.md
index a4dea5b6d..896c5013f 100644
--- a/doc/en/Authoring/Inclusions.md
+++ b/doc/en/Authoring/Inclusions.md
@@ -1,17 +1,10 @@
 # Inclusions
 
-This is an expert level topic, please avoid this feature unless you feel that you 
-understand the implications and concecuences of it. Note that using this feature
-goes against the self-contained material principle present in [the future proof guidelines](Future_proof.md).
+This is an expert level topic, please avoid this feature unless you feel that you understand the implications and consequences of it. Note that using this feature goes against the self-contained material principle present in [the future proof guidelines](Future_proof.md).
 
-That being said, a common request on the wish-list has been to provide some means
-of sharing code between questions. The inclusion-feature is the first step towards
-such a feature, however, it is not perfect nor do we expect it to be the solution 
-that will finally be selected. But we provide it now that the backend has the tools
-to provide it, for those adventurous enough.
+That being said, a common request on the wish-list has been to provide some means of sharing code between questions. The inclusion-feature is the first step towards such a feature, however, it is not perfect nor do we expect it to be the solution that will finally be selected. But we provide it now that the back-end has the tools to provide it, for those adventurous enough.
 
-Technical note: Currently, inclusions within inclusions are not supportted, due to
-loop detection and security validation reasons.
+Technical note: Currently, inclusions within inclusions are not supported, due to loop detection and security validation reasons.
 
 ## Inclusions life-cycle
 
@@ -24,8 +17,8 @@ The logic will not track changes to the source material, if one wants to fetch i
 again one must re-compile the question, either by purging the caches or by editing
 the question.
 
-Note that in the current solution during export we export only the source address 
-and the exported material will only work if the address is accessible at the end 
+Note that in the current solution during export we export only the source address
+and the exported material will only work if the address is accessible at the end
 that imports it.
 
 
@@ -34,13 +27,13 @@ that imports it.
 The simpler inclusion type is the CASText2 include-block, which will simply place
 CASText2-code from a given address at the blocks location. Note that one may need
 to be careful with the format of the context and included code, the include logic
-assumes that the code is of the same format as the context, so if your included 
-content is in Markdown-format including it directly to HTML-context may cause 
+assumes that the code is of the same format as the context, so if your included
+content is in Markdown-format including it directly to HTML-context may cause
 trouble.
 
 Typical use case would be to have a JSXGraph or GeoGebra plotting logic that expect that
 certain variables contain parameters for plotting and one would then simply
-make sure that one would populate those parameters before inclusion of the plotting 
+make sure that one would populate those parameters before inclusion of the plotting
 logic for example like this:
 
 ```
@@ -53,29 +46,29 @@ Then include the same plotting logic but change the parameters to plot something
 
 ```
 
-As the included content can be of a different format (Markdown etc.) than 
+As the included content can be of a different format (Markdown etc.) than
 the context into which it gets included it is recommended that the included
-content defines its own format. For example, wrapping itself in one of 
+content defines its own format. For example, wrapping itself in one of
 the new format controlling blocks `[[moodleformat]]`, `[[htmlformat]]` or
 `[[markdownformat]]`, thus allowing whatever format content to be included
-within another formats content. Note, that at this time identification of 
+within another formats content. Note, that at this time identification of
 math-mode is not quite ready to understand all of these context switches.
 
 
 ## Inclusions within CAS-logic
 
 You can also include code into keyvals, i.e. question-variables or into feedback-variables.
-This type of an inclusion will again act just as if written directly by the question author at that place in the code. If one writes this type of an inclusion within an if-statement it will simply get written open within 
+This type of an inclusion will again act just as if written directly by the question author at that place in the code. If one writes this type of an inclusion within an if-statement it will simply get written open within
 an if-statement, the `if` will only decide if it executes, but it will still take that space and bandwidth.
 
 The included material must follow all the rules of normal STACK keyvals.
 
-1. Large amounts of code will affect performance.  The internal Maxima code is pre-compiled but question variables are interpreted at runtime.  
+1. Large amounts of code will affect performance.  The internal Maxima code is pre-compiled but question variables are interpreted at runtime.
 2. All the identifiers bound in included code will subject to checks just as if you typed them in.
 3. Identifiers in your code will be marked as forbidden-words for the students. So particular care should be taken when choosing identifiers in such shared logic between questions.  Do not use names a student might need to type in another, un-related, question!
 4. Code is loaded when you save the question, not when a student uses the question.  Hence code is cached in the question.  Updates to an external library will therefore not affect existing questions.  That cache will not invalidate unless you (a) update the STACK plugin (which clears all cached/compiled questions), (b) save the question (which again downloads the code).
 
-Note that we do not do "tree-shaking" at this point to remove unnecessary code.  If you include a massive library of functions that you do not use the question will still have to load those functions into the CAS and that may take some time.  If you have libraries, used in many questions, please consider contibuting these to the core of STACK.
+Note that we do not do "tree-shaking" at this point to remove unnecessary code.  If you include a massive library of functions that you do not use the question will still have to load those functions into the CAS and that may take some time.  If you have libraries, used in many questions, please consider contributing these to the core of STACK.
 
 To include external CAS code call the `stack_include()`-function with a string  argument.  The argument must be a raw string, containing the URL of the code.  You cannot reference a variable containing such a string. For example,
 
@@ -91,9 +84,9 @@ m: mymatrix_rand_integer_invertible(a);
 You may not use evaluation flags with `stack_include()` while the code included may
 have them the inclusion call cannot be used to apply flags to all the included content.
 
-The function `stack_include_contrib()` will load the files contained in the 
+The function `stack_include_contrib()` will load the files contained in the
 [STACK maxima contrib folder](https://github.com/maths/moodle-qtype_stack/tree/master/stack/maxima/contrib) in the master branch in github.
-In particular the argument of `stack_include_contrib()` has this URL prepended: 
+In particular the argument of `stack_include_contrib()` has this URL prepended:
 `https://raw.githubusercontent.com/maths/moodle-qtype_stack/master/stack/maxima/contrib/`
 
 Hence, the following are completely equivalent
@@ -103,13 +96,13 @@ Hence, the following are completely equivalent
 
 Notes.
 
-1. We will try to keep files in the contrib folder small, and stable.  
+1. We will try to keep files in the contrib folder small, and stable.
 2. We intend to move commonly used contributed code into the core in due course.  At that point we will localise language strings for automatic translation.
 3. Please contact the developers about naming conventions.  For example, external validators should start the function name with `validator_`.
 
 ### Sandbox testing
 
-Note, that `stack_include()` and has no Maxima-side equivalent so you cannot simply copy-paste 
+Note, that `stack_include()` and has no Maxima-side equivalent so you cannot simply copy-paste
 your question-variables into Maxima to debug things. You will need to manually do that inclusion.
 
 `stack_include_contrib()` will load the packages from the local STACK files, when you set up the sandbox.
diff --git a/doc/en/Authoring/Inputs.md b/doc/en/Authoring/Inputs.md
index 24157d10f..90f9a7d09 100644
--- a/doc/en/Authoring/Inputs.md
+++ b/doc/en/Authoring/Inputs.md
@@ -1,6 +1,6 @@
 # Inputs
 
-Inputs are the points at which the student interacts with the question.  
+Inputs are the points at which the student interacts with the question.
 The default (and prototype) is an HTML input box into which a student is expected to type an algebraic expression.
 
 * Only the [question text](CASText.md#question_text) may have inputs.
@@ -119,7 +119,7 @@ This input type can be used for
 1. surveys;
 2. answers which are not automatically marked, contributing to [semi-automatic marking](../Moodle/Semi-automatic_Marking.md).
 
-The notes input has a special extra option `manualgraded`, and the default option value is `manualgraded:false`.  If you specify `manualgraded:true` then the _whole STACK quesion_ will require manual grading!
+The notes input has a special extra option `manualgraded`, and the default option value is `manualgraded:false`.  If you specify `manualgraded:true` then the _whole STACK question_ will require manual grading!
 
 #### Single Character ####
 
@@ -147,7 +147,7 @@ There are six options.
 * Insert `*`s for implied multiplication.  If any patterns are identified as needing `*`s then they will automatically be inserted into the expression quietly.
 * Insert `*`s assuming single character variable names.  In many situations we know that a student will only have single character variable names.  Identify variables in the student's answer made up of more than one character then replace these with the product of the letters.
   * Note, the student's formula is interpreted and variables identified, so \(\sin(ax)\) will not end up as `s*i*n*(a*x)` but as `sin(a*x)`.
-  * Note, in interpreting the student's formula we build an internal tree in order to identify variable names and function names.  Hence \(xe^x\) is interpreted as \( (xe)^x \).  We then identify the variable name `xe` and replace this as `x*e`.  Hence, using this option we have `xe^x` is interpreted as `(x*e)^x` NOT as `x*e^x` which you might expect.  
+  * Note, in interpreting the student's formula we build an internal tree in order to identify variable names and function names.  Hence \(xe^x\) is interpreted as \( (xe)^x \).  We then identify the variable name `xe` and replace this as `x*e`.  Hence, using this option we have `xe^x` is interpreted as `(x*e)^x` NOT as `x*e^x` which you might expect.
 
 There are also additional options to insert multiplication signs for spaces.
 
@@ -157,7 +157,7 @@ There are also additional options to insert multiplication signs for spaces.
 
 If a space is taken for multiplication what should we do with \(\sin\ x\)?  Currently this is transformed to \(\sin \times x\) and then rejected as invalid as you can't multiply the function name by its argument.  Use these latter options with caution: in the long run students are likely to need to use a strict syntax with machines, and letting them use spaces now might be a disservice.
 
-It is often very important to have some on-screen representation of multiplication, e.g. as a dot, so the student can see at the validation that `xe^x` is interpreted 
+It is often very important to have some on-screen representation of multiplication, e.g. as a dot, so the student can see at the validation that `xe^x` is interpreted
 
 1. as \( (x\cdot e)^x\) if we assume single character variable names, and
 2. as \( xe^x\) if we just "Insert `*`s for implied multiplication".  The absence of the dot here is key.
@@ -234,15 +234,15 @@ Another useful way of avoiding this problem is to put a LaTeX string such as \(y
 
 ### Student must verify ### {#Student_must_verify}
 
-Specifies whether the student's input is presented back to them before scoring as part of a two-step validation process.  
-Typically the student's mathematical expression is displayed in traditional form.  
+Specifies whether the student's input is presented back to them before scoring as part of a two-step validation process.
+Typically the student's mathematical expression is displayed in traditional form.
 This is useful for complex algebraic expressions but not needed for constrained input like `yes`/`no`.
 
-Experience strongly supports the use of this two-step verification process.  
-Errors will always be displayed and expressions with errors rejected as invalid. 
+Experience strongly supports the use of this two-step verification process.
+Errors will always be displayed and expressions with errors rejected as invalid.
 Potential response trees will not execute with invalid input.
 
-The next option controls how the validation feedback is displayed. 
+The next option controls how the validation feedback is displayed.
 Note, it is not possible to require a two-step validation but not show some validation feedback.
 
 ### Show validation ### {#Show_validation}
@@ -276,7 +276,7 @@ Our experience strongly suggests this option should only be used for edge cases,
 
 If you use this option when students navigate away from a page the system will "validate" the inputs, and hence any empty boxes will be considered an active empty choice by the student and will be assessed.  If you use this option there is no way to distinguish between an active empty answer choice, and a student who deletes their answer.  (The same problem occurs with radio buttons....)
 
-There are (unfortunately) some edge cases where it is useful to permit the execution of a PRT without all the inputs containing significant content.  
+There are (unfortunately) some edge cases where it is useful to permit the execution of a PRT without all the inputs containing significant content.
 
 Assume you have three inputs `ans1`, `ans2`, `ans3` contributing to a PRT, all of which have the `allowempty` option set because you don't want to tell the student which might be empty.  Assume the correct answer has at least one entry non-empty.  Then, make the first node of the PRT check
 
@@ -288,7 +288,7 @@ If a teacher has three inputs `ans1`, `ans2`, `ans3`, then they can define a set
 
     sa:setdifference({ans1,ans2,ans3},{EMPTYANSWER})
 
-The variable `sa` will be a set containing the non-empty answers (if any).  
+The variable `sa` will be a set containing the non-empty answers (if any).
 
 The teacher can use the `EMPTYANSWER` tag as a "correct answer".
 
@@ -330,7 +330,7 @@ More information on subscripts is given in the atoms and subscripts section of t
 
 As of STACK 4.4.0, there is an option to check, or allow comparison between, variables which occur in the student's answer and the teacher's answer.
 
-This option takes the form of `checkvars:n`, where `n` is an integer. Ommiting this option is equivalent to setting `n=0`.
+This option takes the form of `checkvars:n`, where `n` is an integer. Omitting this option is equivalent to setting `n=0`.
 
 The binary bits are used to set this options.
 
@@ -343,7 +343,7 @@ The numerical argument provides potential for future-proofing features (e.g. cas
 
 ### Extra option: validator ###
 
-This allows an input to add additional bespoke validation, based on a function defined by the question author.  For example, you can define a function which checks if the student's answer is a _list of exactly three floating point numbers_.  See the [validator documetation](../CAS/Validator.md) for more details.
+This allows an input to add additional bespoke validation, based on a function defined by the question author.  For example, you can define a function which checks if the student's answer is a _list of exactly three floating point numbers_.  See the [validator documentation](../CAS/Validator.md) for more details.
 
 Writing bespoke validators is an advanced feature, but offers two significant benefits.
 
@@ -360,10 +360,10 @@ It is often sensible to use a prefix just in front of the form box.  For example
 
     \(f(x)=\) [[input:ans1]].
 
-This avoids all kinds of problems with students also trying to enter the prefix themselves.  
+This avoids all kinds of problems with students also trying to enter the prefix themselves.
 You could also specify units afterwards, but you might also want the student to type these in!
 
-In Maxima the input `(a,b,c)` is a programmatic block element (see Maxima's manual for `block`). 
+In Maxima the input `(a,b,c)` is a programmatic block element (see Maxima's manual for `block`).
 Hence we cannot use this directly for the input of coordinates.  Instead, have the students type in an unnamed function like
 
     P(x,y)
@@ -380,40 +380,40 @@ This table lists all options, and which inputs use/respect them.  The `.` means
 
 Options           | Alg | Num | Units | Matrix | Check | Radio | Drop | T/F | TextArea | Equiv | String | Notes
 ------------------|-----|-----|-------|--------|-------|-------|------|-----|----------|-------|--------|------
-Box size          |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    Y     |   Y   |   Y    |   Y  
-Strict Syn        |  Y  | (1) |  (1)  |   Y    |   .   |   .   |   .  |  .  |    Y     |   Y   |   .    |   .  
-Insert stars      |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    Y     |   Y   |   .    |   .  
-Syntax hint       |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    Y     |   Y   |   Y    |   Y  
-Hint att          |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    Y     |   Y   |   Y    |   Y  
-Forbidden words   |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    Y     |   Y   |   .    |   .  
-Allowed words     |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    Y     |   Y   |   .    |   .  
-Forbid float      |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    Y     |   Y   |   .    |   .  
-Lowest terms      |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    Y     |   Y   |   .    |   .  
-Check type        |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    .     |   .   |   .    |   .  
-Must verify       |  Y  |  Y  |  Y    |   Y    |   Y   |   Y   |   Y  |  Y  |    Y     |   Y   |   Y    |   .  
-Show validation   |  Y  |  Y  |  Y    |   Y    |   Y   |   Y   |   Y  |  Y  |    Y     |   Y   |   Y    |   .  
-**Extra options:**|     |     |       |        |       |       |      |     |          |       |        |      
-`rationalize`   |  Y  |  Y  |  .    |   .    |   .   |   .   |   .  |  .  |    .     |   .   |   .    |   .  
-min/max sf/dp     |  .  |  Y  |  Y    |   .    |   .   |   .   |   .  |  .  |    .     |   .   |   .    |   .  
-`floatnum`      |  .  |  Y  |  .    |   .    |   .   |   .   |   .  |  .  |    .     |   .   |   .    |   .  
-`intnum`        |  .  |  Y  |  .    |   .    |   .   |   .   |   .  |  .  |    .     |   .   |   .    |   .  
-`rationalnum`   |  .  |  Y  |  .    |   .    |   .   |   .   |   .  |  .  |    .     |   .   |   .    |   .  
-`consolidatesubscripts` |  Y  |  .  |  Y    |   Y    |   .   |   .   |   .  |  .  |    .     |   .   |   .    |   .  
-`negpow`        |  .  |  .  |  Y    |   .    |   .   |   .   |   .  |  .  |    .     |   .   |   .    |   .  
-`simp`            |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    Y     |   .   |   .    |   .  
-`align`        |  Y  |  Y  |  Y    |   .    |   .   |   .   |   .  |  .  |    .     |   .   |   .    |   .  
-`nounits`      |  Y  |  Y  |  Y    |   Y    |   Y   |   Y   |   Y  |  .  |    .     |   Y   |   .    |   .  
-`checkvars`    |  Y  |  .  |  .    |   Y    |   .   |   .   |   .  |  .  |    .     |   Y   |   .    |   .  
-`validator`    |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    .     |   .   |   Y    |   .  
+Box size          |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    Y     |   Y   |   Y    |   Y
+Strict Syn        |  Y  | (1) |  (1)  |   Y    |   .   |   .   |   .  |  .  |    Y     |   Y   |   .    |   .
+Insert stars      |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    Y     |   Y   |   .    |   .
+Syntax hint       |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    Y     |   Y   |   Y    |   Y
+Hint att          |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    Y     |   Y   |   Y    |   Y
+Forbidden words   |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    Y     |   Y   |   .    |   .
+Allowed words     |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    Y     |   Y   |   .    |   .
+Forbid float      |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    Y     |   Y   |   .    |   .
+Lowest terms      |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    Y     |   Y   |   .    |   .
+Check type        |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    .     |   .   |   .    |   .
+Must verify       |  Y  |  Y  |  Y    |   Y    |   Y   |   Y   |   Y  |  Y  |    Y     |   Y   |   Y    |   .
+Show validation   |  Y  |  Y  |  Y    |   Y    |   Y   |   Y   |   Y  |  Y  |    Y     |   Y   |   Y    |   .
+**Extra options:**|     |     |       |        |       |       |      |     |          |       |        |
+`rationalize`   |  Y  |  Y  |  .    |   .    |   .   |   .   |   .  |  .  |    .     |   .   |   .    |   .
+min/max sf/dp     |  .  |  Y  |  Y    |   .    |   .   |   .   |   .  |  .  |    .     |   .   |   .    |   .
+`floatnum`      |  .  |  Y  |  .    |   .    |   .   |   .   |   .  |  .  |    .     |   .   |   .    |   .
+`intnum`        |  .  |  Y  |  .    |   .    |   .   |   .   |   .  |  .  |    .     |   .   |   .    |   .
+`rationalnum`   |  .  |  Y  |  .    |   .    |   .   |   .   |   .  |  .  |    .     |   .   |   .    |   .
+`consolidatesubscripts` |  Y  |  .  |  Y    |   Y    |   .   |   .   |   .  |  .  |    .     |   .   |   .    |   .
+`negpow`        |  .  |  .  |  Y    |   .    |   .   |   .   |   .  |  .  |    .     |   .   |   .    |   .
+`simp`            |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    Y     |   .   |   .    |   .
+`align`        |  Y  |  Y  |  Y    |   .    |   .   |   .   |   .  |  .  |    .     |   .   |   .    |   .
+`nounits`      |  Y  |  Y  |  Y    |   Y    |   Y   |   Y   |   Y  |  .  |    .     |   Y   |   .    |   .
+`checkvars`    |  Y  |  .  |  .    |   Y    |   .   |   .   |   .  |  .  |    .     |   Y   |   .    |   .
+`validator`    |  Y  |  Y  |  Y    |   Y    |   .   |   .   |   .  |  .  |    .     |   .   |   Y    |   .
 
 For documentation about the various options not documented on this page look at the pages for the specific inputs in which each option is used.
 
 Notes:
 
-1. The numerical and units input type ignore the strict syntax option and always assume strict syntax is "true".  
+1. The numerical and units input type ignore the strict syntax option and always assume strict syntax is "true".
 Otherwise patterns for scientific numbers such as `2.23e4` will have multiplication characters inserted.
 
 ## Other input types ##
 
-Adding new inputs, or options for existing inputs, is a job for the developers.  
+Adding new inputs, or options for existing inputs, is a job for the developers.
 The only essential requirement is that the result is a valid CAS expression, which includes of course a string data type, or a list.
diff --git a/doc/en/Authoring/JSXGraph.md b/doc/en/Authoring/JSXGraph.md
index 51ae240e1..8a1a4b879 100644
--- a/doc/en/Authoring/JSXGraph.md
+++ b/doc/en/Authoring/JSXGraph.md
@@ -1,6 +1,6 @@
 # JSXGraph
 
-This page documents use of JSXGraph to display visuals. This is a somewhat advanced topic. For basic plots and visuals you may prefer to [use Maxima to plot graphs](../Plots/Plots.md). 
+This page documents use of JSXGraph to display visuals. This is a somewhat advanced topic. For basic plots and visuals you may prefer to [use Maxima to plot graphs](../Plots/Plots.md).
 
 STACK supports inclusion of dynamic graphs using JSXGraph: [http://jsxgraph.uni-bayreuth.de/wiki/](http://jsxgraph.uni-bayreuth.de/wiki/).
 
@@ -38,11 +38,11 @@ To make a working question, you will then need to add in `fx` as the model answe
 
 ## Block options
 
-You can control the size of the JSXGraph board with the `width` and `height` options.  E.g. 
+You can control the size of the JSXGraph board with the `width` and `height` options.  E.g.
 
     [[jsxgraph width="200px" height="200px"]]
 
-The option `aspect-ratio` combinet with the ability to use relative dimensions allows for graphs to resize and maintain its shape if the viewport changes. When using `aspect-ratio` it is necessary to define one and only one of the above lengths.
+The option `aspect-ratio` combined with the ability to use relative dimensions allows for graphs to resize and maintain its shape if the viewport changes. When using `aspect-ratio` it is necessary to define one and only one of the above lengths.
 
     [[jsxgraph width="80%" aspect-ratio="3/2"]]
 
@@ -83,17 +83,17 @@ In this example we provide a simple slider.  Notice in this example we use the J
     [[jsxgraph]]
       /* boundingbox:[left, top, right, bottom] */
       var board = JXG.JSXGraph.initBoard(divid, {boundingbox: [-5, 10, 5, -10], axis: true, showCopyright: false});
-      var a = board.create('slider',[[-3,6],[2,6],[0,2,6]],{name:'a'}); 
+      var a = board.create('slider',[[-3,6],[2,6],[0,2,6]],{name:'a'});
       var curve = board.create('functiongraph', [function(x) {return a.Value()**x}], {strokeWidth:2});
       board.unsuspendUpdate();
     [[/jsxgraph]]
 
 ## General considerations when building interactive graphs {#manual_binding}
 
-In general you should pay attention on how your graph reacts to the student returning to the page/question later. For example, will your graph 
-reset to display the original situation or will it at least move all movable things to the positions the student last left them? If 
-the student can do things that are not actually considered as part of the answer, e.g. zoom out or pan the view, do you also remember 
-those actions? If your graph is not used for inputting answers then this is not a major issue but if it is then you will need to solve 
+In general you should pay attention on how your graph reacts to the student returning to the page/question later. For example, will your graph
+reset to display the original situation or will it at least move all movable things to the positions the student last left them? If
+the student can do things that are not actually considered as part of the answer, e.g. zoom out or pan the view, do you also remember
+those actions? If your graph is not used for inputting answers then this is not a major issue but if it is then you will need to solve
 this issue. Basically, storing the state of the interactive graph is a key thing that the author of that graph needs to deal with.
 
 The basic structure of such graph logic is as follows:
@@ -102,7 +102,7 @@ The basic structure of such graph logic is as follows:
  2. Draw the graph based on that state.
  3. Attach listeners to everything that can be changed in the graph and store those changes into the state in those listeners.
 
-The simplest solution for storing state is to add a `string` type input field to the question. 
+The simplest solution for storing state is to add a `string` type input field to the question.
 
  1. Create and hide an input with CSS, e.g. `<p style="display:none">[[input:stateStore]] [[validation:stateStore]]</p>` (but probably not while you develop the question!)
  2. Make the input a "string" type.
@@ -115,22 +115,22 @@ You can use that input field to store the state of the graph as a string, for ex
 
 
     [[jsxgraph input-ref-stateStore="stateRef"]]
-      /* Note that the input-ref-X attribute above will store the element identifier of the input X in 
+      /* Note that the input-ref-X attribute above will store the element identifier of the input X in
          a variable named in the attribute, you can have multiple references to multiple inputs. */
-    
+
       /* Create a normal board. */
       var board = JXG.JSXGraph.initBoard(divid, {axis: true, showCopyright: false});
-    
+
       /* State represented as a JS-object, first define default then try loading the stored values. */
       var state = {'x':4, 'y':3};
       var stateInput = document.getElementById(stateRef);
       if (stateInput.value && stateInput.value != '') {
         state = JSON.parse(stateInput.value);
       }
-    
+
       /* Then make the graph represent the state */
       var p = board.create('point',[state['x'],state['y']]);
-    
+
       /* And finally the most important thing, update the stored state when things change. */
       p.on('drag', function() {
         var newState = {'x':p.X(), 'y':p.Y()};
@@ -144,13 +144,13 @@ You can use that input field to store the state of the graph as a string, for ex
 
 Note, in the above example in `[[jsxgraph input-ref-stateStore="stateRef"]]` the `stateStore` part of this tag directly relates to, and must match, the name of the input.
 
-In that trivial example you only have one point that you can drag around but the position of that point will be stored and it will be where 
-you left it when you return to the page. However, the position has been stored in a String encoded in JSON format and cannot directly be 
-used in STACK-side logic. The JSON format is however very handy if you create objects to store dynamically and want to represent things 
-of more complex nature, but in this example we could have just as well have had two separate Numeric inputs storing just the raw 'x' 
+In that trivial example you only have one point that you can drag around but the position of that point will be stored and it will be where
+you left it when you return to the page. However, the position has been stored in a String encoded in JSON format and cannot directly be
+used in STACK-side logic. The JSON format is however very handy if you create objects to store dynamically and want to represent things
+of more complex nature, but in this example we could have just as well have had two separate Numeric inputs storing just the raw 'x'
 and 'y' coordinates separately as raw numbers and in that case we could have used them directly in STACK's grading logic.
 
-If needed, JSON is not impossible to parse in STACK, but it is not easy (as in JavaScript) because Maxima has no map 
+If needed, JSON is not impossible to parse in STACK, but it is not easy (as in JavaScript) because Maxima has no map
 data-structures and is not object oriented. In any case, the JSON string generated in the previous example would look like this:
 
     stateStore:"{\"x\":4,\"y\":3}";
@@ -173,10 +173,10 @@ The example in the previous section about moving the point around and storing th
     [[jsxgraph input-ref-stateStore="stateRef"]]
       /* Create a board like normal. */
       var board = JXG.JSXGraph.initBoard(divid, {axis: true, showCopyright: false});
-    
+
       /* Create a point, its initial position will be the default position if no state is present. */
       var p = board.create('point', [4, 3]);
-    
+
       /* Bind it to the input and state stored in it. */
       stack_jxg.bind_point(stateRef, p);
     [[/jsxgraph]]
@@ -216,30 +216,30 @@ One use case of this could be tying together a STACK `[[input]]` with an Input o
     <p>Enter \(\sin(x)\)</p>
     <span hidden="">[[input:ans1]]</span><span>[[validation:ans1]]</span><br>
     [[jsxgraph width="200px" height="100px" input-ref-ans1="ans1Ref"]]
-    	let board = JXG.JSXGraph.initBoard(divid, { 
+    	let board = JXG.JSXGraph.initBoard(divid, {
           boundingbox: [-1,1,1,-1], axis: false
         });
       	let inputBox = board.create('input',[0,0,'',''],{}); /*Create input box we want to bind to the STACK input*/
-       
+
         /* We want to create our own binding function using custom_bind as a base.
            Our function, inputBinder, will take the reference to the STACK input and the object we want to bind to it as inputs.
            The serializer function doesn't take any inputs, but will refer to the object given to inputBinder directly.
            The deserializer function takes exactly one input: the data with which it will update the graph.
            Lastly, we run the custom_bind function. */
-        
+
         let inputBinder = function(inputRef, object) {
             let serializer = function() {return object.Value()} /*Simply returns the value in the inputBox*/
             let deserializer = function(data) {object.set(data)} /*Given some data, put this data into the inputBox*/
             stack_jxg.custom_bind(inputRef, serializer, deserializer, [object])
         }
-        
+
         /* Now we run the function */
         inputBinder(ans1Ref, inputBox)
 	[[/jsxgraph]]
 
-In most cases the `serializer` and `deserializer` functions will be a bit more complicated, and will probably need to use functions like `JSON.stringify` or `JSON.parse` as in the earlier examples on this page. 
+In most cases the `serializer` and `deserializer` functions will be a bit more complicated, and will probably need to use functions like `JSON.stringify` or `JSON.parse` as in the earlier examples on this page.
 
-Sometimes you may wish to bind a STACK input to something in the JSXGraph IFRAME that isn't an object, in which case the `stack_jxg.custom_bind` will not work. One example of this would be asking students to identify or shade in a certain region in a graph, such as part of a Venn diagram, identifying the region of integration for an iterated integral, or showing that (for example), two sixths is equal to one third. In this case, you will need to write the binding more explicitly, using the steps listed above as a framework. An example is given below, in which we ask the student to "shade" in one third of a circle divided into six equal segments. 
+Sometimes you may wish to bind a STACK input to something in the JSXGraph IFRAME that isn't an object, in which case the `stack_jxg.custom_bind` will not work. One example of this would be asking students to identify or shade in a certain region in a graph, such as part of a Venn diagram, identifying the region of integration for an iterated integral, or showing that (for example), two sixths is equal to one third. In this case, you will need to write the binding more explicitly, using the steps listed above as a framework. An example is given below, in which we ask the student to "shade" in one third of a circle divided into six equal segments.
 
 Let us first assume that we will hard-code this question to always ask students to shade in one third of a circle divided into sixths. This is not too difficult to generalise, and it keeps the code clean. Then let us define a model answer as the list:
 
@@ -247,24 +247,24 @@ Let us first assume that we will hard-code this question to always ask students
 
 We interpret this as two of the six sectors in our eventual graph being shaded, and four of them being unshaded, with 1 representing on and 0 representing off. Our student input, `ans1`, will then be a normal algebraic input.
 
-Now we can create the question text. Firstly, we state the instructions for the student and create the board and associated objects. 
+Now we can create the question text. Firstly, we state the instructions for the student and create the board and associated objects.
 
     <p>Shade some regions of the diagram below so that it represents the fraction \(\dfrac{1}{3}\). Click a region to shade it, and click a second time to un-shade it if needed.</p>
     [[jsxgraph width="500px" height="500px" input-ref-ans1="ans1Ref"]]
         var board = JXG.JSXGraph.initBoard(divid, {
 	        boundingbox: [-1.2,1.2,1.2,-1.2], axis: false,
             showNavigation: false, showCopyright: false});
-  
+
         var plotColours = ["#1f77b4", "#ff7f0e"];
         var numSectors = 6;
-  
+
         var origin = board.create('point',[0,0],{visible:false}); /* This will be referenced multiple times as we create the sectors */
-        
+
         var points = [];
         var sectors = [];
 
         /* Create 7 points (doubling up the start and end) and then between each pair of adjacent points, define a sector. */
-        
+
         var sectorAttr = {strokeColor:plotColours[0],strokeOpacity:0.5,strokeWidth: 2,fillColor:plotColours[1],fillOpacity:0, highlight: false}
         for(let ii=0;ii<numSectors+1;ii++) {
             points[ii] = board.create('point',[Math.cos(ii*2*Math.PI / numSectors),Math.sin(ii*2*Math.PI / numSectors)],{visible:false});
@@ -273,7 +273,7 @@ Now we can create the question text. Firstly, we state the instructions for the
             }
         }
 
-Now that the graph has been drawn, we need to initialise the shading based on existing student input. This means that if a student has given an answer and then refreshed the page, the graph should show the correct sectors shaded or unshaded based on that answer. 
+Now that the graph has been drawn, we need to initialise the shading based on existing student input. This means that if a student has given an answer and then refreshed the page, the graph should show the correct sectors shaded or unshaded based on that answer.
 
     var shading = [0,0,0,0,0,0];
     var shadingInput = document.getElementById(ans1Ref);
@@ -284,7 +284,7 @@ Now that the graph has been drawn, we need to initialise the shading based on ex
         }
     }
 
-The graph should now have the appropriate shading applied. We have completed the first two out of three steps as outlined above. To accomplish the last step we will write three functions; one that will return the coordinates of a location that is clicked, andother that will update the graph given those coordinates, and a third that will listen to a click event and then run these functions. 
+The graph should now have the appropriate shading applied. We have completed the first two out of three steps as outlined above. To accomplish the last step we will write three functions; one that will return the coordinates of a location that is clicked, another that will update the graph given those coordinates, and a third that will listen to a click event and then run these functions.
 
     /* The below code is adapted from an example found at https://jsxgraph.org/wiki/index.php/Browser_event_and_coordinates */
 
diff --git a/doc/en/Authoring/Multiple_choice_questions.md b/doc/en/Authoring/Multiple_choice_questions.md
index 212f612bd..0e40f7a56 100644
--- a/doc/en/Authoring/Multiple_choice_questions.md
+++ b/doc/en/Authoring/Multiple_choice_questions.md
@@ -2,7 +2,7 @@
 
 The whole point of STACK is not to use multiple-choice questions, but instead to have the student enter an algebraic expression!  That said there are occasions where it is very useful, if not necessary, to use multiple-choice questions in their various forms.  STACK's use of a CAS is then very helpful to generate random variants of multiple-choice questions based on the mathematical values.
 
-This can also be one input in a multi-part randomly generated question. E.g. you might say "which method do you need to integrate \( \sin(x)\cos(x) \)?" and give students the choice of (i) trig functions first, 
+This can also be one input in a multi-part randomly generated question. E.g. you might say "which method do you need to integrate \( \sin(x)\cos(x) \)?" and give students the choice of (i) trig functions first,
 (ii) parts, (iii) substitution, (iv) replace with complex exponentials.  (Yes, this is a joke: all these methods can be made to work here!)  Another algebraic input can then be used for the answer.
 
 Please read the section on [inputs](Inputs.md) first.  If you are new to STACK please note that in STACK MCQs are *not* the place to start learning how to author questions.  Please look at the [authoring quick-start guide](Authoring_quick_start.md).
@@ -16,7 +16,7 @@ The goal of these input types is to provide *modest* facilities for MCQ.  An ear
 
 ## Model answer ##
 
-This input type uses the "model answer" both to input the teacher's answer and the other options. 
+This input type uses the "model answer" both to input the teacher's answer and the other options.
 In this respect, this input type is unique, and the "model answer" field does *not* contain just the teacher's model answer.  Constructing a correctly formed model answer is complex, and so this input type should be considered "advanced".  New users are advised to gain confidence writing questions with algebraic inputs first, and gain experience in using Maxima lists.
 
 The "model answer" must be supplied in a particular form as a list of lists `[[value, correct(, display)], ... ]`.
@@ -36,9 +36,9 @@ STACK provides some helper functions
 1. `mcq_correct(ta)` takes the "model answer" list and returns a list of values for which `correct` is true.
 2. `mcq_incorrect(ta)` takes the "model answer" list and returns a list of values for which `correct` is false.
 
-Note, that the optional `display` field is *only* used when constructing the choices seen by the student when displaying the question.  The student's answer will be the `value`, and this value is normally displayed to the student using the validation feedback, i.e. "Your last answer was interpreted as...". A fundamental design principal of STACK is that the student's answer should be a mathematical expression, and this input type is no exception.  
+Note, that the optional `display` field is *only* used when constructing the choices seen by the student when displaying the question.  The student's answer will be the `value`, and this value is normally displayed to the student using the validation feedback, i.e. "Your last answer was interpreted as...". A fundamental design principal of STACK is that the student's answer should be a mathematical expression, and this input type is no exception.
 
-In situations where there is a significant difference between the optional `display` and the `value` which would be confusing, the only current option is to turn off validation feedback.  After all, this should not be needed anyway with this input type.  In the example above when a student is asked to choose the right method the `value` could be an integer and the display is some kind of string.  
+In situations where there is a significant difference between the optional `display` and the `value` which would be confusing, the only current option is to turn off validation feedback.  After all, this should not be needed anyway with this input type.  In the example above when a student is asked to choose the right method the `value` could be an integer and the display is some kind of string.
 
 An example which includes the `display` option is
 
@@ -46,17 +46,17 @@ An example which includes the `display` option is
 
 Note in this example the `value` of the student's answer will be a letter which is literally a Maxima variable name.  In this situation you can't really randomize the letters used easily.  (Not impossible with some cunning code, but a lot of work....)
 
-If you choose to use an integer, and randomly suffle the answers then the validation feedback would be confusing, since an integer (which might be shuffled) has no correspondence to the choices selected.  *This behaviour is a design decision and not a bug! It may change in the future if there is sufficient demand, but it requires a significant change in STACK's internals to have parallel "real answer" and "indicated answer". Such a change might have other unintended and confusing consequences.*
+If you choose to use an integer, and randomly shuffle the answers then the validation feedback would be confusing, since an integer (which might be shuffled) has no correspondence to the choices selected.  *This behaviour is a design decision and not a bug! It may change in the future if there is sufficient demand, but it requires a significant change in STACK's internals to have parallel "real answer" and "indicated answer". Such a change might have other unintended and confusing consequences.*
 
 Normally we don't permit duplicate values in the values of the teacher's answer.  If the input type receives duplicate values STACK will throw an error.  This probably arises from poor randomization.  However it may be needed.  If duplicate entries are permitted use the display option to create unique value keys with the same display. *This behaviour is a design decision may change in the future.*
 
-When STACK displays the "teacher's answer", e.g. after a quiz is due, this will be constructed from the `display` fields corresponding to those elements for which `correct` is `true`.  I.e. the "teacher's answer" will be a list of things which the student could actually select.  Whether the student is able to select more than one, or if more than one is actually included, is not checked.  The teacher must indicate at least one choice as `true`.  
+When STACK displays the "teacher's answer", e.g. after a quiz is due, this will be constructed from the `display` fields corresponding to those elements for which `correct` is `true`.  I.e. the "teacher's answer" will be a list of things which the student could actually select.  Whether the student is able to select more than one, or if more than one is actually included, is not checked.  The teacher must indicate at least one choice as `true`.
 
 If you need "none of these" you must include this as an explicit option, and not rely on the student not checking any boxes in the checkbox type.  Indeed, it would be impossible to distinguish the active selection of "none of these" from a passive failure to respond to the question.
 
 If one of the responses is \(x=1 \mbox{ or } x=2\) then it is probably best to use `nounor` which is commutative and associative.  Do not use `or` which always simplifies its arguments.  In this example `x=1 or x=2` evaluates to `false`.
 
-HTML dropdowns cannot display LaTeX within the options.  This is a restriction of HTML/MathJax (not of STACK).  You can use HTML-entities within a string field.  For example 
+HTML dropdowns cannot display LaTeX within the options.  This is a restriction of HTML/MathJax (not of STACK).  You can use HTML-entities within a string field.  For example
 
     ta1:[[0,false,"n/a"],[1,true,"&ge;"],[2,false,"&le;"],[3,false,"="],[4,false,"?"]];
 
@@ -117,12 +117,12 @@ To enable a student to indicate "none of the others", the teacher must add this
 
 The radio and dropdown types always add a "not answered" option as the first option.  This allows a student to retract their choice, otherwise they will be unable to "uncheck" a radio button, which will be stored, validated and possibly assessed (to their potential detriment).  If you want to remove this then use the extra option `nonotanswered`, but keep in mind the possible effect when using the penalty scheme.
 
-If one of the items in the teacher's answer list is is the special variable name `notanswered`, and then default mesage `(Clear my choice)` will be replaced by the `display` value.  If no `display` value is given (and it is optional) then the original message will remain.  `notanswered` will not appear in the list of valid choices for a user and `value` for this input is ingored.
+If one of the items in the teacher's answer list is is the special variable name `notanswered`, and then default message `(Clear my choice)` will be replaced by the `display` value.  If no `display` value is given (and it is optional) then the original message will remain.  `notanswered` will not appear in the list of valid choices for a user and `value` for this input is ingored.
 
 
 ## Extra options ##
 
-These input types make use of the "Extra options" field of the input type to pass in options.  These options are not case sensitive.  
+These input types make use of the "Extra options" field of the input type to pass in options.  These options are not case sensitive.
 This must be a comma-separated list of values as follows, but currently the only option is to control the display of mathematical expressions.
 
 The way the items are displayed can be controlled by the following options.
@@ -152,21 +152,19 @@ For example, the question variables might look like the following.
     tao:[null, false, "None of these"];
     ta:append(ta,[tao]);
 
-These commands ensure (1) the substantive options are in a random order, and (2) that the `None of these` always comes at the end of the list. 
-Note, the value for the `None of these` is the CAS atom `null`.  
-In Maxima `null` has no special significance but it is a useful atom to use in this situation.
+These commands ensure (1) the substantive options are in a random order, and (2) that the `None of these` always comes at the end of the list. Note, the value for the `None of these` is the CAS atom `null`. In Maxima `null` has no special significance but it is a useful atom to use in this situation.
 
 As the Question Note, you might like to consider just taking the first item from each list, for example:
 
     {@maplist(first,ta)@}.  The correct answer is {@tac@}.
 
-This note stores both the correct answer and the order shown to the student without the clutter of the `true/false` values or the optional display strings.  
+This note stores both the correct answer and the order shown to the student without the clutter of the `true/false` values or the optional display strings.
 Remember, random variants of a question are considered to be the same if and only if the question note is the same,
 so the random order must be part of the question note if you shuffle the options.
 
 ## Constructing MCQ arrays in Maxima ##
 
-It is not easy to construct MCQ arrays in Maxima.  This section contains some tips for creating them, using Maxima's `lambda` command.  
+It is not easy to construct MCQ arrays in Maxima.  This section contains some tips for creating them, using Maxima's `lambda` command.
 Below is an example of a correctly constructed teacher's answer.
 
     ta:[[x^2-1,true],[x^2+1,false],[(x-1)*(x+1),true],[(x-i)*(x+i),false]]
@@ -175,8 +173,8 @@ To create a list of correct answers you could use the function `mcq_correct(ta)`
 
     maplist(first, sublist(ta, lambda([ex], second(ex))));
 
-The function `sublist` "filters" out those entries of `ta` for which the second element of the list is true.  
-We then "map" first onto these entries to pull out the value.  
+The function `sublist` "filters" out those entries of `ta` for which the second element of the list is true.
+We then "map" first onto these entries to pull out the value.
 It is relatively simple to modify this code to extract the incorrect entries, the displayed forms of the correct entries etc.
 
 To go in the other direction, the first list `ta1` is considered "correct" and the second `ta2` is considered incorrect.
@@ -189,7 +187,7 @@ To go in the other direction, the first list `ta1` is considered "correct" and t
     /* If you want to shuffle the responses then use the next line. */
     ta:random_permutation(ta);
 
-Also, you can use STACK's `rand_selection(L, n)` to select \(n\) different elements from the list \(L\).  
+Also, you can use STACK's `rand_selection(L, n)` to select \(n\) different elements from the list \(L\).
 Say you have the following list of wrong answers and you want to take only 3 out of 5.
 
     ta2:[x^2,w^2,w^6,z^4,2*z^4];
@@ -198,7 +196,7 @@ Say you have the following list of wrong answers and you want to take only 3 out
     ta2:maplist(lambda([ex],[ex, false]), ta2);
 
 
-Another way to create an MCQ answer list is to have Maxima decide which of the answers are true.  
+Another way to create an MCQ answer list is to have Maxima decide which of the answers are true.
 For example, in this question the student has to choose which of the answers are integers.
 
     L:[1,4/2,3.0,2.7,1/4,%pi,10028];
@@ -215,12 +213,12 @@ STACK has helper functions to create MCQ arrays in Maxima.
 
     [ta, variant] = multiselqn(corbase, numcor, wrongbase, numwrong)
 
-This function takes two lists `corbase` and `wrongbase` and two integers `numcor` and `numwrong`.  
-It randomly selects `numcor` from `corbase`, and `numwrong` from `wrongbase` and then creates the MCQ list `ta` with these selections, 
+This function takes two lists `corbase` and `wrongbase` and two integers `numcor` and `numwrong`.
+It randomly selects `numcor` from `corbase`, and `numwrong` from `wrongbase` and then creates the MCQ list `ta` with these selections,
 and an answernote `variant`.
 
-The function returns a list with two arguments.  
-The first argument of the list is the MCQ array, the second is just the list of answers which is useful for the answer note.  
+The function returns a list with two arguments.
+The first argument of the list is the MCQ array, the second is just the list of answers which is useful for the answer note.
 Note, this function does use `random_permutation` internally to randomly order the random selections.
 
 For example, the following generates random expressions for an MCQ calculus question.  Note the use of `ev(...)` later to evaluate the derivative.
@@ -254,7 +252,7 @@ For example, here the return values could be
 
 The function `multiselqndisplay` automatically assigns numbers \(1,\cdots, k\) to the `corbase` entries, and then \(k+1,\cdots, n\) to the `wrongbase` entries so that the numbers returned by the input type uniquely map to the entries in the two lists regardless of which random variant is generated.  These numbers are useful internally, but not for students.
 
-The function `multiselqnalpha` automatically selects the appropriate number of correct and incorrect entries, permutes the list and then assigns strings `"(a)"`, `"(b)"`, `"(c)"` etc. in the correct order. The student's answer will thus be a list of strings (somewhat subverting the whole purpose of STACK in returning a genuine mathematical expression, but this has its place...).  
+The function `multiselqnalpha` automatically selects the appropriate number of correct and incorrect entries, permutes the list and then assigns strings `"(a)"`, `"(b)"`, `"(c)"` etc. in the correct order. The student's answer will thus be a list of strings (somewhat subverting the whole purpose of STACK in returning a genuine mathematical expression, but this has its place...).
 
     [ta, variant] = multiselqnalpha(corbase, numcor, wrongbase, numwrong, [dispstyle])
 
@@ -268,7 +266,7 @@ Notes
 1. The fifth optional argument to ` multiselqnalpha` controls the display style of the LaTeX.  Use `"i"` (a string containing `i`) for inline, `"d"` for displayed and `"id"` for inline "displaystyle" (which is the default).
 2. Note that the "student's" answer will now be a _string_ such as `"(a)"`.  When you construct the PRT you will not need to check against these strings, not the original CAS expressions.
 3. The `variant` retains the CAS statements, in order.
-4. Do not use `multiselqnalpha` in conjunction with the `shuffle` option.  There is no need as the selection are permuted, and it messes up the order of the choices for the student. 
+4. Do not use `multiselqnalpha` in conjunction with the `shuffle` option.  There is no need as the selection are permuted, and it messes up the order of the choices for the student.
 
 
 ## Dealing with strings in MCQ ##
@@ -276,7 +274,7 @@ Notes
 A likely situation is that a teacher wants to include a language string as one of the options for a student's answer in a multiple-choice question.
 
 Recall: *A fundamental design principal of STACK is that the student's answer should be a mathematical expression which can be
-manipulated by the CAS as a valid expression.* Students are very limited in the keywords they are permitted to use in an input type.  
+manipulated by the CAS as a valid expression.* Students are very limited in the keywords they are permitted to use in an input type.
 It is very likely that strings will contain keywords forbidden in student expressions.
 
 One option to overcome this is to do something like this as one option in the teacher's response:
@@ -297,7 +295,7 @@ You must protect characters within strings.  E.g. in
 
 We have protected the backslash, and the inequality.
 
-The language strings are not CAStext, they are simply raw strings.  It is possible to construct strings which inlcude variable values using the `stack_disp` function.
+The language strings are not CAStext, they are simply raw strings.  It is possible to construct strings which include variable values using the `stack_disp` function.
 
     [oc(-inf,a), false, sconcat("The half interval: ", stack_disp(oc(-inf,a),"i"))]
 
@@ -314,18 +312,18 @@ Since 4.4 it has been possible to write more complex labels using inline CASText
 
 You may write normal CASText syntax inside that string and it should behave exactly like it does in question-text or PRT feedback etc.. The only limitation at this time is that the list that includes these labels must be defined in the question-variables, you may not write inline CASText directly to the model answer field of the input. The `castext()`-function is not a real CAS-function it is converted to more complex logic at compile time and therefore it must receive a static string as its argument.
 
-The most obvious use case for inline CASText is to provide localisation inside MCQ labels in situatiosn where the mlang2-filter is not an option:
+The most obvious use case for inline CASText is to provide localisation inside MCQ labels in situations where the mlang2-filter is not an option:
 
     [true, true, castext("[[lang code='en']]Yes[[/lang]][[lang code='fi']]Kyllä[[/lang]]")]
 
 ## Dealing with plots in MCQ ##
 
-It is possible to use plots as the options in a STACK MCQ.  
+It is possible to use plots as the options in a STACK MCQ.
 
-Recall again the MCQ are limited to legitimate CAS objects.  
-The `plot` command returns a string which is the URL of the dynamically generated image on the server.  
-The "value" of this can't be assessed by the potential response trees.  
-For this reason you must use the display option with plots and must only put the plot command in the display option. (Otherwise STACK will throw an error: this behaviour could be improved).  
+Recall again the MCQ are limited to legitimate CAS objects.
+The `plot` command returns a string which is the URL of the dynamically generated image on the server.
+The "value" of this can't be assessed by the potential response trees.
+For this reason you must use the display option with plots and must only put the plot command in the display option. (Otherwise STACK will throw an error: this behaviour could be improved).
 For example, to create a correct answer consisting of three plots consider the following in the question variables.
 
     p1:plot(x,[x,-2,2],[y,-3,3])
@@ -333,17 +331,17 @@ For example, to create a correct answer consisting of three plots consider the f
     p3:plot(x^3,[x,-2,2],[y,-3,3])
     ta:[[1,true,p1],[2,false,p2],[3,false,p3]]
 
-The actual CAS value of the answer returned will be the respective integer selected (radio or dropdown) or list of integers (checkbox).  
-The PRT can then be used to check the value of the integer (or list) as normal.  
+The actual CAS value of the answer returned will be the respective integer selected (radio or dropdown) or list of integers (checkbox).
+The PRT can then be used to check the value of the integer (or list) as normal.
 
-For this reason you will probably want to switch off the validation feedback ``your last answer was...".  
+For this reason you will probably want to switch off the validation feedback ``your last answer was...".
 
 Using a PRT is slight overkill, but it maintains the consistent internal design.
 
 ## Dealing with external images in MCQ ##
 
-It is also possible to embed the URL of an externally hosted image as the "display" field of an MCQ.  
-The string is not checked, and is also passed through the CAS.  
+It is also possible to embed the URL of an externally hosted image as the "display" field of an MCQ.
+The string is not checked, and is also passed through the CAS.
 This feature is fragile to being rejected as an invalid CAS object, and so is not recommended.  (This could also be improved...)
 
 For example, the question variables could be something like
@@ -356,7 +354,7 @@ For example, the question variables could be something like
 
 ## Writing question tests ##
 
-Quality control of questions is important.  See the notes on [testing](Testing.md) questions.  
+Quality control of questions is important.  See the notes on [testing](Testing.md) questions.
 
 When entering test cases the question author must type in the CAS expression they expect to be the `value` of the student's answer (NOT the optional `display` field!).  For example, if the teacher's answer (to a checkbox) question is the following.
 
@@ -366,4 +364,4 @@ Then the following test case contains all the "true" answers.
 
      [x^2-1,(x-1)*(x+1)]
 
-There is currently minimal checking that the string entered by the teacher corresponds to a valid choice in the input type.  If your test case returns a blank result this is probably the problem.     
+There is currently minimal checking that the string entered by the teacher corresponds to a valid choice in the input type.  If your test case returns a blank result this is probably the problem.
diff --git a/doc/en/Authoring/Notes_about_performance.md b/doc/en/Authoring/Notes_about_performance.md
index 0c007a9f2..b3e3864db 100644
--- a/doc/en/Authoring/Notes_about_performance.md
+++ b/doc/en/Authoring/Notes_about_performance.md
@@ -10,7 +10,7 @@ While not everyone uses them and not everyone needs to use them, they do improve
 
 If you are running on a truly large scale or if your servers cannot keep up, always look at [deployed variants](./Deploying.md) first.
 
-Just make your question notes informative, the prefered way is to show the question and the answer for this particular variant in short form; a simple parameter list may help, but it is often less than helpful.
+Just make your question notes informative, the preferred way is to show the question and the answer for this particular variant in short form; a simple parameter list may help, but it is often less than helpful.
 
 ## Randomisation loops are really bad!
 
@@ -21,13 +21,13 @@ So don't write anything like this:
 	foo: rand(.....);
 	while not is_good(foo) do foo: rand(.....);
 
-Not only is there a risk that some seed of the random number generator never leads to parameters that end up being "good", but that can also lead to wildly varying execution times and even timeouts. 
+Not only is there a risk that some seed of the random number generator never leads to parameters that end up being "good", but that can also lead to wildly varying execution times and even timeouts.
 
 If you cannot write code that directly randomises a "good" result, you should use deployed variants and question-tests to pre-randomise and select only the cases where the randomisation is "good", the key is to use question-tests as the filter here.
 
 ## Big strings or things you might not want to place in question-variables.
 
-In the STACK question model, it is assumed that whatever is in the question-variables or in any other code/logic block is data and needs to be fully transferred into the CAS during all processing steps of the question; conversely, whatever is present in the question-text or other text content is assumed to be safe and not "data". We do special sidelining of such safe "not data" and don't send it all the way to CAS if we can avoid it, and it still rejoins the output once necessary.
+In the STACK question model, it is assumed that whatever is in the question-variables or in any other code/logic block is data and needs to be fully transferred into the CAS during all processing steps of the question; conversely, whatever is present in the question-text or other text content is assumed to be safe and not "data". We do special side-lining of such safe "not data" and don't send it all the way to CAS if we can avoid it, and it still rejoins the output once necessary.
 
 This means that if you place big strings on the logic side without actually using them there, you are probably wasting resources. If that text is intended as something to be outputted in the text itself then one should look at putting it into the text itself, maybe using [CASText features](./Question_blocks/index.md) that allow conditional inclusion if need be.
 
@@ -41,4 +41,4 @@ Currently (pre input2), the number of inputs in a question affects the number of
 
 ## Number of PRTs affected the performance.
 
-If you have large numbers of PRTs and are not running 4.4 or later, you might gain significant performance boosts if you update to 4.4. In the earlier versions, every PRT was evaluated separately in their own CAS session, but now they get handled in a single session. Every new session always incurs a performance overhead, so joining them does give us some benefits.
\ No newline at end of file
+If you have large numbers of PRTs and are not running 4.4 or later, you might gain significant performance boosts if you update to 4.4. In the earlier versions, every PRT was evaluated separately in their own CAS session, but now they get handled in a single session. Every new session always incurs a performance overhead, so joining them does give us some benefits. 
\ No newline at end of file
diff --git a/doc/en/Authoring/Parsons.md b/doc/en/Authoring/Parsons.md
index dc59d8921..1a990c872 100644
--- a/doc/en/Authoring/Parsons.md
+++ b/doc/en/Authoring/Parsons.md
@@ -2,7 +2,7 @@
 
 Parson’s problems require students to assemble pre-written text into a correct order by dragging blocks into a tree structure.  This block is needed to hold the javascript and strings which students can drag.
 
-STACK provides a `[[parsons]] ... [[/ parsons]]` [question block](Question_blocks/index.md).  The question author pre-defines strings.  These strings can be defined as Maxima variables in the question text, or just defined within the question block itself.
+STACK provides a `[[parsons]] ... [[/ parsons]]` [question block](Question_blocks/index.md).  The question author pre-defines strings to drag within the block.  These strings can be defined as Maxima variables in the question text, or just defined within the question block itself.
 
 Users interact with the strings, dragging them into a tree structure.  Note, a list is a special case of a more structured tree.  The block can be linked to a STACK input so that the student's configuration can be stored and/or assessed.  This page is reference documentation for the `[[parsons]]` block.  Documentation on how to use this block in a complete question is given under topics: [Authoring Parson's problems](../Topics/Parsons.md).
 
@@ -44,16 +44,18 @@ Both these approaches can be combined
 [[/parsons]]
 ````
 
+Note the `\` character needs to be protected within strings, so for example we have to type `\\(n=2m+1\\)` rather than just `\(n=2m+1\)`.
+
 ## Customising the `[[parsons]]` block
 
 ### JSON "options"
 
-The `[[parsons]]` block is a wrapper for the javascript library "Sortable.js", optimised and with default options for Parson's problems. Moreover, there are default settings we add in, such as the headers for each of the two lists. These may be customised by structuring the JSON in the block contents as follows: 
+The `[[parsons]]` block is a wrapper for the javascript library "Sortable.js", optimised and with default options for Parson's problems. Moreover, there are default settings we add in, such as the headers for each of the two lists. These may be customised by structuring the JSON in the block contents as follows:
 
 ````
 [[parsons input="ans1"]]
 { "steps": {# stackjson_stringify(proof_steps) #},
-  "options": {"header" : ["custom header for the answer list", "custom header for the available steps"],
+  "options": {"header" : ["Custom header for the answer list", "Custom header for the available steps"],
               "sortable option 1" : value,
               ...
               "sortable option n" : value}
@@ -84,13 +86,13 @@ Note that if you enter an unknown sortable option or if an attempt to pass `ghos
 
 Functionality and styling can be customised through the use of block parameters.
 
-1. `input`: string. The name of the STACK input variable (e.g., `"ans1"`), this links to an internal `state` parameter that updates the input as a Maxima expression so that it can be evaluated by a PRT.
+1. `input`: string. The name of the STACK input variable (e.g., `"ans1"`), this links to an internal `state` parameter that updates the input as a Maxima expression so that it can be stored and evaluated by a PRT.
 2. `height`: string containing a positive float + a valid CSS unit (e.g.`"480px"`, `"100%"`, ...). Default is to create a window of automatic height to fit all the content upon load. Entering a value for the `height` parameter in the block header fixes the height of the window containing the drag-and-drop lists and will disable automatic resizing of the window containing the lists. Students will still be able to automatically resize the window with the expand button.
 3. `width`: string containing a positive float + a valid CSS unit (e.g.`"480px"`, `"100%"`, ...).  Default is `"100%"`. This fixes the width of the window containing the drag-and-drop lists.
 4. `aspect-ratio`: string, containing a float between 0 and 1. This can be used with `height`/`length` _or_ `width` (not both) and automatically determines the value of the un-used parameter in accordance with the value of `aspect-ratio`; unset by default. An error will occur if one sets values for `aspect-ratio`, `width`, `height` _or_ `aspect-ratio`, `width`, `length`.
 5. `clone`: string of the form `"true"` or `"false"`. It is `"false"` by default. When `"false"` there are two lists and each proof step is "single-use", here the author must write all necessary proof steps even if they repeat; when `"true"` all proof steps are re-usable with no restrictions on how many times they are used, steps can only be dragged from the available list into the answer list, and there is a bin to tidy up steps.
 6. `orientation`: string of the form `"horizontal"` or `"vertical"`. This can be used to fix the initial orientation shown to the user, `"horizontal"` will show lists side-by-side and `"vertical"` will show lists on top of each other. Note that there is a button on the page in which the user may switch the orientation to their preference while answering the question, so the `"orientation"` block parameter only determines the initial layout. It is `"horizontal"` by default.
-7. `override-css`: string containing the location of a local CSS file contained in `question/type/stack/corsscripts/` directory in the format `cors://file-name` or a href to an external CSS stylesheet. This will override all CSS styling of the drag-and-drop listing, so it should be used with care. However, it can be used to customise the styling of the lists by writing one's own custom CSS file and passing in the location of that file to this parameter. This parameter is unset by default. 
+7. `override-css`: string containing the location of a local CSS file contained in `question/type/stack/corsscripts/` directory in the format `cors://file-name` or a href to an external CSS stylesheet. This will override all CSS styling of the drag-and-drop listing, so it should be used with care. However, it can be used to customise the styling of the lists by writing one's own custom CSS file and passing in the location of that file to this parameter. This parameter is unset by default.
 8. `override-js`: string containing a local JavaScript library or a href to a cdn of a JavaScript library. This will overwrite the Sortable library used with the library identified by the string. This should be used if one wishes to use an updated version of the Sortable library, or adding functionality with a custom library. Note that the custom library will need to either extend or import the base Sortable functionality. Unset by default.
 9. `version`: string of the form `"local"` or `"cdn"`. Whether to use STACK's local copy of the Sortable library or whether to pull version 1.15.0 of Sortable from cdn. This is `"local"` by default.
 
@@ -157,7 +159,7 @@ Notice that since the value of `plot(...)` is a Maxima string of `<img>` tag, th
 [[/parsons]]
 ````
 
-An alternatove is to use the Maxima `castext` function, e.g.
+An alternative is to use the Maxima `castext` function, e.g.
 
     s1:castext("Consider this graph {@plot(x^2,[x,-1,1],[size,250,250])@}");
 
@@ -185,4 +187,4 @@ proof_steps:[
 
 ## Adding trees to a Parson's block
 
-STACK enables question authors to display the tree structure of an algebraic expression using castext `{@disptree(1+2+pi*x^3)@}`.  
+STACK enables question authors to display the tree structure of an algebraic expression using castext `{@disptree(1+2+pi*x^3)@}`.
diff --git a/doc/en/Authoring/Potential_response_trees.md b/doc/en/Authoring/Potential_response_trees.md
index 5bf570b08..fee478e5d 100644
--- a/doc/en/Authoring/Potential_response_trees.md
+++ b/doc/en/Authoring/Potential_response_trees.md
@@ -8,7 +8,7 @@ Each potential response tree relies on one or more of the [inputs](Inputs.md). S
 
 ## Before the tree is traversed ##
 
-Each potential response tree can set Maxima's level of [simplification](../CAS/Simplification.md). Before the tree is traversed the [feedback variables](Variables.md#Feedback_variables) are evaluated. The feedback variables may depend on the values of the [question variables](Variables.md#Question_variables) and the [inputs](Inputs.md). The values of these variables are available to the [answer tests](Answer_Tests/index.md) and all [CASText](CASText.md) fields within the tree, for example the feedback could be built using these variables.
+Each potential response tree can set Maxima's level of [simplification](../CAS/Simplification.md). Before the tree is traversed the [feedback variables](Variables.md#Feedback_variables) are evaluated. The feedback variables may depend on the values of the [question variables](Variables.md#Question_variable.s) and the [inputs](Inputs.md). The values of these variables are available to the [answer tests](Answer_Tests/index.md) and all [castext](CASText.md) fields within the tree, for example the feedback could be built using these variables.
 
 Notes:
 
@@ -26,7 +26,7 @@ In each node two expressions are compared using a specified [answer tests](Answe
 2. Add written feedback specifically for the student
 3. Generate an "[answer note](Potential_response_trees.md#Answer_note)", used by the teacher for evaluative assessment
 4. Nominate the next node, or end the process.
-5. Any runtime error during traversing the tree will cause an error.  This error will stop further exectution of the tree, and students will see a runtime error message.  This will be flagged in the response summary as `[RUNTIME_ERROR]`.  If you have statements likely to throw an error you should evaluate them in the feedback variables first. See notes on [error trapping](Error_trapping.md) for advice on how to use this.
+5. Any runtime error during traversing the tree will cause an error.  This error will stop further execution of the tree, and students will see a runtime error message.  This will be flagged in the response summary as `[RUNTIME_ERROR]`.  If you have statements likely to throw an error you should evaluate them in the feedback variables first. See notes on [error trapping](Error_trapping.md) for advice on how to use this.
 
 ## Outcomes  ##
 
@@ -51,16 +51,16 @@ This field is given a default value automatically and is used for [reporting](Re
 
 This field may not be empty and for each node in a tree the string must be unique.
 
-Do not use `;`, `|` charaters in your answer note.  These characters are used to split the response summary in the reporting scripts.
+Do not use `;`, `|` characters in your answer note.  These characters are used to split the response summary in the reporting scripts.
 
 ## Scores and penalties ##
 
 A score is generated by each potential response tree.  Because the tree is only traversed when all inputs are valid, the score is only generated for a valid attempt.
 
-If a score is generated it is based only on the current values of the inputs.  This means that it is not based on either (1) previous values of the inputs, or (2) the number of previous attempts.  (Requests have been made to enable attempt number to be available, but this has not been implemented 
+If a score is generated it is based only on the current values of the inputs.  This means that it is not based on either (1) previous values of the inputs, or (2) the number of previous attempts.  (Requests have been made to enable attempt number to be available, but this has not been implemented
 yet.)
 
-If a score is generated then a penalty is also generated. The penalty system is designed to encourage students to make repeated attempts in a formative setting.  For example, a student is asked to find  \( \int x^2, \mathrm{d}x\).  
+If a score is generated then a penalty is also generated. The penalty system is designed to encourage students to make repeated attempts in a formative setting.  For example, a student is asked to find  \( \int x^2, \mathrm{d}x\).
 
 Attempt 1:  \( x^3/3\).  Score \(=0\), Penalty \(=0.1\), Feedback: "You have missed a constant of integration."
 
@@ -70,10 +70,10 @@ Overall, the potential response tree returns the current score minus total penal
 
 In this example, some colleagues would prefer to give partial credit for missing a constant of integration rather than zero marks and a penalty.  In a formative setting, where students have an opportunity to have another attempt, the penalty system has been found to be an effective way to encourage students to have another attempt and to read the feedback.  In an examination, where no feedback is available and so further attempts are not made, different choices need to be made and partial credit would be more appropriate than a zero mark.
 
-* The penalty is given a default value in the question.  This is a mandatory field; the default for STACK is 0.1.  
-* Penalties are cumulative, but the student will be given the maximum possible mark.  I.e. while they accumulate penalties they are never worse off by repeatedly attempting the question.  In particular, if the student in the above example makes another attempt and scores \(0\) they will retain their mark of \(0.9\).  This is to encourage students to have another go in a formative setting.  STACK generates a list of penalty adjusted scores for each attempt, and takes the maximum. 
-* The penalty can be assigned a different value in the nodes of the potential response tree. This means, e.g., the teacher can assign a cumulative penalty 
-for a particular answer. 
+* The penalty is given a default value in the question.  This is a mandatory field; the default for STACK is 0.1.
+* Penalties are cumulative, but the student will be given the maximum possible mark.  I.e. while they accumulate penalties they are never worse off by repeatedly attempting the question.  In particular, if the student in the above example makes another attempt and scores \(0\) they will retain their mark of \(0.9\).  This is to encourage students to have another go in a formative setting.  STACK generates a list of penalty adjusted scores for each attempt, and takes the maximum.
+* The penalty can be assigned a different value in the nodes of the potential response tree. This means, e.g., the teacher can assign a cumulative penalty
+for a particular answer.
 * The penalties are also controlled at a quiz level by the "question behaviours" mechanism for the quiz.  Hence, if you set the behaviour as "Adaptive mode (no penalties)" the penalty assigned will be ignored when the question is used by students in the quiz.
 
 ## Formative potential response trees ##
@@ -96,18 +96,18 @@ The feedback created by PRTs has the following parts concatenated together.
 
     [Generic feedback] [Runtime errors] [PRT generated feedback] [Score ?]
 
-The `[Generic feedback]` is a question level option, e.g. "Standard feedback for correct", to provide consistency accross a question. By default the `[Generic feedback]` contains both an initial symbol, and a language sentence.  The current "correct" default is
+The `[Generic feedback]` is a question level option, e.g. "Standard feedback for correct", to provide consistency across a question. By default the `[Generic feedback]` contains both an initial symbol, and a language sentence.  The current "correct" default is
 
 <span style="font-size: 1.5em; color:green;"><i class="fa fa-check"></i></span> Correct answer, well done.
 
 How PRT feedback is displayed is controlled by the PRT option `feedbackstyle` as follows.  Note the Generic feedback might include the symbol, if you retain the default.
 
-Value | Options      | Symbol | Generic feedback | Errors | PRT feedback | Score ? 
+Value | Options      | Symbol | Generic feedback | Errors | PRT feedback | Score ?
 ------|--------------|--------|------------------|--------|--------------|------------------------------------------
   0   | Formative    |  No    |  No              |  Yes   |  Yes         | No (PRT does not contribute to score)
   1   | Standard     |  No    |  Yes             |  Yes   |  Yes         | Respects quiz setting
   2   | Compact      |  Yes   |  No              |  Yes   |  Yes         | No
   3   | Symbol only  |  Yes   |  No              |  Yes   |  No          | No
 
-Note that the "Compact" PRT feedback uses `<span>` tags and not `<div>`.  This allows inclusion inline, without new paragraphs settings.  However, `<span>` tags cannot contain a block level element, such as a `<div>` or `<p>`. So, if you include a block level element in your PRT feedback then the browser may "spit this out" and misplace the feedback. Also, MathJax may not display mathematics correctly on the page when there is an HTML errror such as this.  If you use the "Compact" feedback, please author only minimal PRT feedback with no block level HTML elements.
+Note that the "Compact" PRT feedback uses `<span>` tags and not `<div>`.  This allows inclusion inline, without new paragraphs settings.  However, `<span>` tags cannot contain a block level element, such as a `<div>` or `<p>`. So, if you include a block level element in your PRT feedback then the browser may "spit this out" and misplace the feedback. Also, MathJax may not display mathematics correctly on the page when there is an HTML error such as this.  If you use the "Compact" feedback, please author only minimal PRT feedback with no block level HTML elements.
 
diff --git a/doc/en/Authoring/Question_blocks/Conditional_blocks.md b/doc/en/Authoring/Question_blocks/Conditional_blocks.md
index d9f9afd30..8414b35d2 100644
--- a/doc/en/Authoring/Question_blocks/Conditional_blocks.md
+++ b/doc/en/Authoring/Question_blocks/Conditional_blocks.md
@@ -62,7 +62,7 @@ the lists or set be shorter/smaller the iteration will stop when the first one e
 
 Because the foreach block needs to evaluate the lists/sets before it can do the iteration, using foreach blocks will require one
 additional CAS evaluation for each nested level of foreach blocks. This has not applied since 4.4. no additional cost is related
-to this block and it is recommended that any repeption that can be removed is removed using this block.
+to this block and it is recommended that any repetition that can be removed is removed using this block.
 
 ## Define block {#define-block}
 
diff --git a/doc/en/Authoring/Question_blocks/Dynamic_blocks.md b/doc/en/Authoring/Question_blocks/Dynamic_blocks.md
index 8c1a0a4ee..b7508190a 100644
--- a/doc/en/Authoring/Question_blocks/Dynamic_blocks.md
+++ b/doc/en/Authoring/Question_blocks/Dynamic_blocks.md
@@ -26,7 +26,7 @@ The reveal block can be used in conjunction with [MCQ](../Multiple_choice_questi
 Use the following question text.
 
     [[input:ans1]] [[validation:ans1]]
-    [[reveal input="ans1" value="5"]] [[input:ans2]] [[validation:ans2]] [[/reveal]] 
+    [[reveal input="ans1" value="5"]] [[input:ans2]] [[validation:ans2]] [[/reveal]]
 
 1. Create input `ans1` as a radio input, with teacher's answer `ta1`.  Don't require or show validation.
 2. Create input `ans2` as an algebraic input, with teacher's answer `ta2`.  Use the extra option `allowempty`.
@@ -44,7 +44,7 @@ Text shown when the button is pressed.
 [[/hint]]
 ```
 
-Notes 
+Notes
 
 1. hint blocks can be nested.
 2. the content of the hint is styled within a `stack-hint-content` div tag.
@@ -62,7 +62,7 @@ STACK supports inclusion of dynamic graphs using JSXGraph: [http://jsxgraph.uni-
 
 ## JSString block ##
 
-A new feature in 4.4 is the `[[jsstring]]` which makes it simpler to produce JavaScript string values out of CASText content. This may be useful for example when generating labels in JSXGraph. The block takes its content and evaluates it as normal CASText and then excapes it as JavaScript string literal.
+A new feature in 4.4 is the `[[jsstring]]` which makes it simpler to produce JavaScript string values out of CASText content. This may be useful for example when generating labels in JSXGraph. The block takes its content and evaluates it as normal CASText and then escapes it as JavaScript string literal.
 
 ```
 var label = [[jsstring]]{@f(x)=sqrt(x)@}[[/jsstring]];
@@ -70,7 +70,7 @@ var label = [[jsstring]]{@f(x)=sqrt(x)@}[[/jsstring]];
 var label = "\\({f\\left(x\\right)=\\sqrt{x}}\\)";
 ```
 
-Note, this block is _not_ designed to output Maxima expressins in JS format. For example, this block will not convert `x^2` into `x**2`.
+Note, this block is _not_ designed to output Maxima expressions in JS format. For example, this block will not convert `x^2` into `x**2`.
 
 ## GeoGebra block ##
 
@@ -79,6 +79,3 @@ STACK supports inclusion of dynamic graphics using GeoGebra: [https://geogebra.o
 ## Parsons block ##
 
 The [Parsons block](../Parsons.md) allows users (e.g. students) to assemble pre-written text into a correct order.  This block can be linked with an input to create a Parsons problem.
-
-
-
diff --git a/doc/en/Authoring/Question_blocks/Static_blocks.md b/doc/en/Authoring/Question_blocks/Static_blocks.md
index b574e7fc8..b5405f8e8 100644
--- a/doc/en/Authoring/Question_blocks/Static_blocks.md
+++ b/doc/en/Authoring/Question_blocks/Static_blocks.md
@@ -44,7 +44,7 @@ The special "debug" block allows question authors to see all the values of varia
 
 ## Format blocks ##
 
-In general CASText is assumed to be written in the format (Markdown, raw HTML, Moodle auto-format) that Moodle defines and which can be selected in the editor if one uses the plain text area editor. However, there are cases where one might need to mix formats withing the CASText itself, one of those cases is the inclusion of content written in another format. In these cases one can wrap the differing part in blocks that declare the format to use for that portion. The blocks used for this are named `[[moodleformat]]`, `[[markdownformat]]`, and `[[htmlformat]]`. In the end all CASText evaluates down to HTML, even if it were written in Markdown-format it will be rendered down to HTML.
+In general CASText is assumed to be written in the format (Markdown, raw HTML, Moodle auto-format) that Moodle defines and which can be selected in the editor if one uses the plain text area editor. However, there are cases where one might need to mix formats within the CASText itself, one of those cases is the inclusion of content written in another format. In these cases one can wrap the differing part in blocks that declare the format to use for that portion. The blocks used for this are named `[[moodleformat]]`, `[[markdownformat]]`, and `[[htmlformat]]`. In the end all CASText evaluates down to HTML, even if it were written in Markdown-format it will be rendered down to HTML.
 
 ## Textdownload block ##
 
@@ -62,7 +62,7 @@ The template block has two parameters, the first being a name which should be a
 
 1. To define a templates value for a given name one simply wraps that value in this block with that name. `[[template name="foobar"]]Whatever is {@whatever@}[[/template]]`. This will not output anything and can also be done in inline CASText either in the question-variables to effect the whole question or in feedback-variables to effect PRTs.
 2. To output that template, one simply uses the empty block form `[[template name="foobar"/]]` which will output whatever has been defined as that templates value or a warning about the template not been defined. One can add a mode parameter `mode="ignore missing"` to not see that warning. Typically, one will use the `[[define/]]` block to change the values used within the template.
-3. For library makers the most common operation mode is the `mode="default"` where the contents of the block are used if no overriding definition can be found. The default value will not define a default template and this intentional, if a template is to be shared then it needs to be defined at a global level where it always gets evaluated while default templates tend to be sensible to use even in conditionally evaluated contexts. Basically, if your library has any CASText that could benefit from being overridable you simply give it a name and wrap it with `[[template name="libarary_xyz" mode="default"]]...[[/template]]` and then maybe document somewhere that this name has this default where these injectable variables have these roles so that people may replace the wording and structure and still use the same values.
+3. For library makers the most common operation mode is the `mode="default"` where the contents of the block are used if no overriding definition can be found. The default value will not define a default template and this intentional, if a template is to be shared then it needs to be defined at a global level where it always gets evaluated while default templates tend to be sensible to use even in conditionally evaluated contexts. Basically, if your library has any CASText that could benefit from being overridden you simply give it a name and wrap it with `[[template name="libarary_xyz" mode="default"]]...[[/template]]` and then maybe document somewhere that this name has this default where these injectable variables have these roles so that people may replace the wording and structure and still use the same values.
 
 Note in the background templates are just functions with CASText values. You can do the same with inline CASText and more importantly building your own functions allows you to use arguments for them and thus makes repetition with varying parameters simpler. For templates no arguments exist, for them the values come from the context where they get placed in, and must therefore be controlled though other means.
 
diff --git a/doc/en/Authoring/Question_blocks/System_blocks.md b/doc/en/Authoring/Question_blocks/System_blocks.md
index 467df20f0..a32e2b343 100644
--- a/doc/en/Authoring/Question_blocks/System_blocks.md
+++ b/doc/en/Authoring/Question_blocks/System_blocks.md
@@ -2,7 +2,7 @@
 
 ## Commonstring block ##
 
-In some circumstances one might see the `[[commonstring/]]` block. While it might not be one that an author would use it might appear when working with built-in labels and their localisations. What it does is that it gets a `key` as a parameter and fetches the matching localised string from STACKs language packs and replaces the block with it. It also provides means for injecting named parameters into those templates with varying simplification and presentation options.
+In some circumstances one might see the `[[commonstring/]]` block. While it might not be one that an author would use it might appear when working with built-in labels and their localisations. What it does is that it gets a `key` as a parameter and fetches the matching localised string from STACK's language packs and replaces the block with it. It also provides means for injecting named parameters into those templates with varying simplification and presentation options.
 
 For example
 
@@ -16,4 +16,4 @@ There are other blocks that have roles inside the system and that transfer infor
 
 For example, `[[pfs]]` is a special block that gets generated by internal logic when we see plugin files (if you place an image into the WYSIWYG editor) in the text, it works as a marker for those files context so that we can combine text from multiple contexts together and still keep track of the origins when the final product gets rendered.
 
-There are blocks that handle the placeholders for inputs, validation, and feedback. Some others deal with translations between forms and postprocessing special types of content.
\ No newline at end of file
+There are blocks that handle the placeholders for inputs, validation, and feedback. Some others deal with translations between forms and postprocessing special types of content. 
\ No newline at end of file
diff --git a/doc/en/Authoring/Serving_out_data.md b/doc/en/Authoring/Serving_out_data.md
index 0001781aa..a317c391c 100644
--- a/doc/en/Authoring/Serving_out_data.md
+++ b/doc/en/Authoring/Serving_out_data.md
@@ -1,6 +1,6 @@
 # Serving out data
 
-In some contexts one wants to generate random data for the students to act on, depending on the ammount of data and whether one expects the students to transfer it to other tools for processing the methods used for serving that data data out vary. Here are some examples.
+In some contexts one wants to generate random data for the students to act on, depending on the amount of data and whether one expects the students to transfer it to other tools for processing the methods used for serving that data data out vary. Here are some examples.
 
 ## HTML-tables
 
@@ -32,7 +32,7 @@ If you only have a small amount of data you may simply print out a table of it a
 
 ## Raw Maxima code
 
-Should you want to just give out Maxima code for use in Maxima or similar enough syntax you may simply use the `{#...#}` injection instead of `{@...@}` and it will output the raw form which is again copy-pastable. However, this does not work well with large amounts of data as the line may become quite long and even selecting it may prove problematic.
+Should you want to just give out Maxima code for use in Maxima or similar enough syntax you may simply use the `{#...#}` injection instead of `{@...@}` and it will output the raw form which can be used for copy-paste. However, this does not work well with large amounts of data as the line may become quite long and even selecting it may prove problematic.
 
 ## File transfer
 
@@ -50,7 +50,7 @@ data: makelist([rand(322)/100.0,rand(600)/100.0,rand(300)/100.0], i, 50);
 
 ```
 [[comment]]Use them like this in the question-text.[[/comment]]
-Load the data from 
+Load the data from
 <a href="[[textdownload name="data.csv"]]{@stack_csv_formatter(data,lab)@}[[/textdownload]]">this file</a> and ...
 ```
 That function returns a string and it takes in the data as a matrix or a list of lists and labels as a list. If no labels are necessary use `false`. Also you can use `stackfltfmt` to control the representation of pure floats in the data. Just in case you meet trouble `labels` is a keyword that cannot be used which is a shame when defining labels.
diff --git a/doc/en/Authoring/Tables.md b/doc/en/Authoring/Tables.md
index 9c1ba83d2..9b25be8d6 100644
--- a/doc/en/Authoring/Tables.md
+++ b/doc/en/Authoring/Tables.md
@@ -1,6 +1,6 @@
 # Tables
 
-STACK provides an intert function `table` for typesetting mathematical tables, provided originally to typeset truth tables in [Propositional Logic](../Topics/Propositional_Logic.md).
+STACK provides an inert function `table` for typesetting mathematical tables, provided originally to typeset truth tables in [Propositional Logic](../Topics/Propositional_Logic.md).
 
 You can create a table directly.  Notice the first row is a heading row.
 
@@ -30,7 +30,7 @@ If you want to identify which entries really are different then you could do som
 
     table_zip_with(lambda([ex1,ex2], is(ex1=ex2)), T1, T2)
 
-If you find yourself manipulating tables, the above funtion provides a starting point.  Please ask the developers to add anything you use regularly.
+If you find yourself manipulating tables, the above function provides a starting point.  Please ask the developers to add anything you use regularly.
 
 ## Examples.
 
@@ -50,4 +50,4 @@ Here we have two tables `T1` is displayed as
 \[ {\begin{array}{c|c|c} a & b & a\rightarrow b\\ \hline \mathbf{F} & \mathbf{F} & \mathbf{T} \\ \mathbf{F} & \mathbf{T} & \mathbf{T} \\ \mathbf{T} & \mathbf{F} & \mathbf{F} \\ \mathbf{T} & \mathbf{T} & \mathbf{T} \end{array}} \]
 and `T2` gives
 \[ {\begin{array}{c|c|c} a & b & \color{red}{\underline{a\oplus b}}\\ \hline \mathbf{F} & \mathbf{F} & \color{red}{\underline{\mathbf{F} }} \\ \mathbf{F} & \mathbf{T} & \mathbf{T} \\ \mathbf{T} & \mathbf{F} & \color{red}{\underline{\mathbf{T} }} \\ \mathbf{T} & \mathbf{T} & \color{red}{\underline{\mathbf{F} }}\end{array}} \]
-Notice in both the effect of `table_bool_abbreviate:true`.
\ No newline at end of file
+Notice in both the effect of `table_bool_abbreviate:true`. 
\ No newline at end of file
diff --git a/doc/en/Authoring/Testing.md b/doc/en/Authoring/Testing.md
index bde887104..6cbd56710 100644
--- a/doc/en/Authoring/Testing.md
+++ b/doc/en/Authoring/Testing.md
@@ -56,11 +56,11 @@ Test cases can include a meaningful description of up to 255 characters.  This f
 
 ## Test case construction and Maxima evaluation
 
-Test cases are always written assuming `simp:false` regardless of the option set elsewhere.  If you want to construct a simplified test case then wrap this in `ev(... , simp)` to simplify the expression generating the test case.  This behaviour is required to enable construction of unsimplified test cases.
+Test cases are always written assuming `simp:false` regardless of the option set elsewhere.  If you want to construct a simplified test case then wrap this in `ev(... , simp)` to simplify the expression generating the test case.  This behaviour is required to enable construction of un-simplified test cases.
 
 Test cases are always written using the period `.` as the decimal separator.  This corresponds to strict Maxima syntax, which teachers should always use.
 
-You can (and should) constuct test cases based on invalid expressions.  If the raw testcase expression cannot be sent to the CAS, e.g. a missing bracket, then this invalidity will be tested.
+You can (and should) construct test cases based on invalid expressions.  If the raw testcase expression cannot be sent to the CAS, e.g. a missing bracket, then this invalidity will be tested.
 
 While test case construction uses `simp:false` Maxima must "evaluate" the expression prior to the result being used by an input as a test case.  This will replace variables by their values.  E.g. the typical case is to define a variable such as `ta` as the teacher's answer in the question variables field and use this throughout the question.  This answer will either be simplified, or not, when the question variables are evaluated.  To construct a test case using the teacher's answer use `ta` as the test case input.
 
diff --git a/doc/en/Authoring/Workflow.md b/doc/en/Authoring/Workflow.md
index fe6187a4f..27495dd57 100644
--- a/doc/en/Authoring/Workflow.md
+++ b/doc/en/Authoring/Workflow.md
@@ -6,7 +6,6 @@ This document contains suggestions for effective question authoring workflow, es
 
 The first task is to create a minimal working question.  At the outset
 
-
 1. add minimal [question variables](Variables.md) to prevent repetition of information in the "Model answer" field of the inputs, and PRT nodes;
 2. use question variables for key information in the question, especially if you intend to create [random variants](../CAS/Random.md) later;
 3. add minimal feedback in the PRTs.
diff --git a/doc/en/CAS/Buggy_rules.md b/doc/en/CAS/Buggy_rules.md
index a146210f4..6caa06965 100644
--- a/doc/en/CAS/Buggy_rules.md
+++ b/doc/en/CAS/Buggy_rules.md
@@ -1,9 +1,6 @@
 # Buggy rules
 
-In order to establish that the student has done something
-particular but wrong, it is useful for us to be able to apply
-wrong or buggy rules to expressions.  A typical example would
-be to expand out powers in the wrong way, e.g.
+In order to establish that the student has done something particular but wrong, it is useful for us to be able to apply wrong or buggy rules to expressions.  A typical example would be to expand out powers in the wrong way, e.g.
 
 \[(x+y)^2=x^2+y^2.\]
 
@@ -27,7 +24,6 @@ Note that both `denom` and `num` work on non-rational expressions, assuming the
 
 This is not always a buggy rule. It is used, for example, in connection with Farey sequences, but it is included here as in assessment this function is useful for checking a common mistake when adding fractions.
 
-
 There is scope for further examples of such rules.
 
 ## See also
diff --git a/doc/en/CAS/Complex_numbers.md b/doc/en/CAS/Complex_numbers.md
index b47034a2a..7110f6730 100644
--- a/doc/en/CAS/Complex_numbers.md
+++ b/doc/en/CAS/Complex_numbers.md
@@ -1,6 +1,6 @@
 # Complex Numbers in STACK
 
-Complex numbers, especially the display of complex numbers, is a surprisingly subtle issue.   This is because there is some genuine ambiguity in whether \(a+\mathrm{i}\, b\) is a single object or the sum of two parts.  In mathematics we use this ambiguity to our advantage, but in online assesment we need to be more precise.  There are also issues of unary minus, e.g. _not_ displaying \(1 + (-2)\mathrm{i}\). Similarly we typically do _not_ display numbers like \(0+1\mathrm{i}\), unless of course we want to at which point we need the option to do so!
+Complex numbers, especially the display of complex numbers, is a surprisingly subtle issue.   This is because there is some genuine ambiguity in whether \(a+\mathrm{i}\, b\) is a single object or the sum of two parts.  In mathematics we use this ambiguity to our advantage, but in online assessment we need to be more precise.  There are also issues of unary minus, e.g. _not_ displaying \(1 + (-2)\mathrm{i}\). Similarly we typically do _not_ display numbers like \(0+1\mathrm{i}\), unless of course we want to at which point we need the option to do so!
 
 The general rules when displaying a complex number in Cartesian form "\(a+\mathrm{i}\, b\)" are
 
@@ -16,7 +16,7 @@ Some examples:
 
 STACK provides two functions, one which simplifies and one which does not.
 
-1. `display_complex(ex)` takes an expression `ex` and tries to display this as a complex number obeying the above rules.  In particular, this function makes use of Maxima's `realpart` and `imagpart` function to split up `ex` into real and imaginary parts.  To do this it must assume `simp:true`, and so the real and imaginary part will be simplified.  For example, `display_complex(1+2*%i/sqrt(2))` is displayed as \(1+\sqrt{2}\,\mathrm{i}\).  If you really want \(1+\frac{2}{\sqrt{2}}\,\mathrm{i}\) then you will need to use the non-simplifying alternative below.  This function respects normal conventions, e.g. when `realpart` returns zero this function will not print \(0+2\,\mathrm{i}\), it just prints \(2\,\mathrm{i}\), etc.  
+1. `display_complex(ex)` takes an expression `ex` and tries to display this as a complex number obeying the above rules.  In particular, this function makes use of Maxima's `realpart` and `imagpart` function to split up `ex` into real and imaginary parts.  To do this it must assume `simp:true`, and so the real and imaginary part will be simplified.  For example, `display_complex(1+2*%i/sqrt(2))` is displayed as \(1+\sqrt{2}\,\mathrm{i}\).  If you really want \(1+\frac{2}{\sqrt{2}}\,\mathrm{i}\) then you will need to use the non-simplifying alternative below.  This function respects normal conventions, e.g. when `realpart` returns zero this function will not print \(0+2\,\mathrm{i}\), it just prints \(2\,\mathrm{i}\), etc.
 2. `disp_complex(a, b)` assumes `a` is the real part and `b` is the imaginary part (no checking is done).  This function (mostly) does not simplify its arguments.  So `disp_complex(0, 2)` will appear as \(0+2\,\mathrm{i}\); `disp_complex(2/4, 1)` will appear as \(\frac{2}{4}+1\,\mathrm{i}\); and `disp_complex(2, 2/sqrt(2))` will appear as \(2+\frac{2}{\sqrt{2}}\,\mathrm{i}\).  Use the atom `null` if you do not want to print a zero for the real part, or print one times the imaginary part.  `disp_complex(null, 2)` will appear as \(2\,\mathrm{i}\) and `disp_complex(null, null)` will appear as just \(\mathrm{i}\).  Think of `null` as a non-printable unit (additive or multiplicative).
 
 There is one exception.  In order to pull out a unary minus to the front, `disp_complex(a, b)` will simplify `b` if `b` is not a number and it contains a unary minus.  So, for example `disp_complex(a, (-b^2)/b)` is displayed \(a-\mathrm{i}\,b\).  (We _might_ be able to fix this but this edge case requires disproportionate effort: ask the developers if this is essential).
@@ -25,7 +25,7 @@ You cannot use these functions to display complex numbers in this form \(\frac{\
 
 Display respects the multiplication sign used elsewhere within expressions, so that you may have \(\frac{2\cdot \pi}{3}\,\mathrm{i}\) rather than \(\frac{2\, \pi}{3}\,\mathrm{i}\).
 
-Note that the function `display_complex(ex)` returns the inert form `disp_complex(a, b)`.  The expression `disp_complex(a, b)` is an "inert form", which is only used to fine-tune the display.  This function is not actually defined and so Maxima always returns it unevaluated.  To remove the intert form from an expression, which is needed to manipulate this further, use `remove_disp_complex`, e.g., with the following.
+Note that the function `display_complex(ex)` returns the inert form `disp_complex(a, b)`.  The expression `disp_complex(a, b)` is an "inert form", which is only used to fine-tune the display.  This function is not actually defined and so Maxima always returns it unevaluated.  To remove the inert form from an expression, which is needed to manipulate this further, use `remove_disp_complex`, e.g., with the following.
 
     p1:disp_complex(a, b);
     p2:ev(p1, disp_complex=remove_disp_complex);
@@ -44,7 +44,7 @@ You must remove inert forms before expressions are evaluated by the potential re
 
 ## Polar forms
 
-A complex number written as \(r e^{i\theta}\) is in _polar form_.  The Maxima function `polarform` re-writes a complex number in this form, however with `simp:false` it does not simplfy the expressions for the modulus \(r\) or argument \(\theta\) (in STACK). Attempting to re-simplify the expression only returns the number to Cartesian form!
+A complex number written as \(r e^{i\theta}\) is in _polar form_.  The Maxima function `polarform` re-writes a complex number in this form, however with `simp:false` it does not simplify the expressions for the modulus \(r\) or argument \(\theta\) (in STACK). Attempting to re-simplify the expression only returns the number to Cartesian form!
 
 As a minimal example, try the following.
 
@@ -57,7 +57,7 @@ First we have `p1` is  \( \left(\left(1\right)^2 + \left(1\right)^2\right)^{{{1}
 
 Notice the difference between `p2`: \(\sqrt{2}\,e^{{{i\,\pi}\over{4}}}\), and `p3`: \(\sqrt{2}\,\left({{i}\over{\sqrt{2}}}+{{1}\over{\sqrt{2}}}\right)\) (which of course is not even \(1+i\) either!).
 
-The problem is that in this case `ev( ... , simp)` is not _idempotent_, (i.e. \( \mbox{simplify}(\mbox{simplify}(ex)) \neq \mbox{simplify}(ex) \) in all cases) and the PHP-maxima connection inevitibly passes an expression to and from Maxima multiple times.  If `simp:true` then we get multiple simplifications, in this example back to `p3`.
+The problem is that in this case `ev( ... , simp)` is not _idempotent_, (i.e. \( \mbox{simplify}(\mbox{simplify}(ex)) \neq \mbox{simplify}(ex) \) in all cases) and the PHP-maxima connection inevitably passes an expression to and from Maxima multiple times.  If `simp:true` then we get multiple simplifications, in this example back to `p3`.
 
 Instead, use `polarform_simp` to rewrite the expression in polar form, and do some basic simplification of \(r\) and \(\theta\).
 
diff --git a/doc/en/CAS/Matrix.md b/doc/en/CAS/Matrix.md
index 6f063f24c..0b2e67e04 100644
--- a/doc/en/CAS/Matrix.md
+++ b/doc/en/CAS/Matrix.md
@@ -88,9 +88,9 @@ For an individual question, the teacher can set the variable
 
 in any of the usual places, e.g. in the question variables.
 
-To set the display of an individual matrix, `m` say, in CASText you can use
+To set the display of an individual matrix, `m` say, in castext you can use
 
-    {@(lmxchar:"|", m)@} 
+    {@(lmxchar:"|", m)@}
 
 Since `lmxchar` is a global setting in Maxima, you will have to set it back when you next display a matrix.  Not ideal, but there we are.
 
@@ -144,7 +144,7 @@ and a student types in `a*x+b*y` then the tex output will be \(a\cdot \mathbf{\v
 
 ### Vector cross product ###
 
-The wedge product operator is denoted by the tilde `~`.  This is the `itensor` package.  This package is not normally loaded by STACK, and in any case the package takes lists and not matrices.  For convenience, the following function has been added which requires `3*1` matrices.  
+The wedge product operator is denoted by the tilde `~`.  This is the `itensor` package.  This package is not normally loaded by STACK, and in any case the package takes lists and not matrices.  For convenience, the following function has been added which requires `3*1` matrices.
 
     crossproduct(a,b);
 
diff --git a/doc/en/CAS/Maxima.md b/doc/en/CAS/Maxima.md
index 078326340..e96c8c131 100644
--- a/doc/en/CAS/Maxima.md
+++ b/doc/en/CAS/Maxima.md
@@ -125,7 +125,7 @@ You can use Maxima's looping structures within Question variables. For example
     n : 1;
     for a:-3 thru 26 step 7 do n:n+a;
 
-The result will be \(n=56\). It is also possible to define functions within the question variables for use within a question. 
+The result will be \(n=56\). It is also possible to define functions within the question variables for use within a question.
 
     f(x) := x^2;
     n : f(4);
@@ -152,10 +152,10 @@ STACK provides an inert function `sequence`.  All this does is display its argum
 * `sequencep` is a predicate to decide if the expression is a sequence.
 * The atom `dotdotdot` is displayed using the tex `\ldots` which looks like \(\ldots\).  This atom cannot be entered by students.
 
-STACK provides an inert function `ntuple`.  All this does is display its arguments with round brackets. For example `ntuple(1,2,3,4)` is displayed \((1,2,3,4)\).  
+STACK provides an inert function `ntuple`.  All this does is display its arguments with round brackets. For example `ntuple(1,2,3,4)` is displayed \((1,2,3,4)\).
 
-* `ntupleify` creates an n-tuple from the arguments of the expression.  This turns lists, sets etc. into an n-tuple. 
-* `ntuplep` is a predicate to decide if the expression is an ntuples. 
+* `ntupleify` creates an n-tuple from the arguments of the expression.  This turns lists, sets etc. into an n-tuple.
+* `ntuplep` is a predicate to decide if the expression is an ntuples.
 
 In strict Maxima syntax `(a,b,c)` is equivalent to `block(a,b,c)`.  If students type in `(a,b,c)` using a STACK input it is filtered to `ntuple(a,b,c)`. Teachers must use the `ntuple` function explicitly to construct question variables, teacher's answers, test cases and so on. The `ntuple` is useful for students to type in coordinates.
 
@@ -179,7 +179,7 @@ Currently, students can enter expressions with "implied ntuples" E.g
 
 * Student input of `(1,2,3)` is interpreted as `ntuple(1,2,3)`.
 * Student input of `{(1,2,3),(4,5,6)}` is interpreted as `{ntuple(1,2,3),ntuple(4,5,6)}`.
-* Since no operations are defined on ntuples, students cannot currenlty enter things like `(1,2,3)+s*(1,0,0)`.  There is nothing to stop a teacher defining the expression tree `ntuple(1,2,3)+s*ntuple(1,0,0)`, but the operations `+` and `*` are not defined for ntuples and so nothing will happen!  If you want a student to enter the equation of a line/plane they should probably use the matrix syntax for vectors.  (This may change in the future).
+* Since no operations are defined on ntuples, students cannot currently enter things like `(1,2,3)+s*(1,0,0)`.  There is nothing to stop a teacher defining the expression tree `ntuple(1,2,3)+s*ntuple(1,0,0)`, but the operations `+` and `*` are not defined for ntuples and so nothing will happen!  If you want a student to enter the equation of a line/plane they should probably use the matrix syntax for vectors.  (This may change in the future).
 
 Matrices have options to control the display of the braces.  Matrices are displayed without commas.
 
diff --git a/doc/en/CAS/Numbers.md b/doc/en/CAS/Numbers.md
index 946c050a1..0e42b77e1 100644
--- a/doc/en/CAS/Numbers.md
+++ b/doc/en/CAS/Numbers.md
@@ -42,11 +42,11 @@ The option [sqrt(-1)](../Authoring/Options.md#sqrt_minus_one) is set in each que
 * To convert to a float use Maxima's `float(ex)` command.
 * To convert a float to an exact representation use `rat(x)` to rationalise the decimal.
 
-The variable \(e\) has been defined as `e:exp(1)`.  This now potentially conflicts with scientific notation `2e3` which means `2*10^3`.    
+The variable \(e\) has been defined as `e:exp(1)`.  This now potentially conflicts with scientific notation `2e3` which means `2*10^3`.
 
-If you expect students to use scientific notation for numbers, e.g. `3e4` (which means \(3\times 10^{4}\) ), then you may want to use the [option for strict syntax](../Authoring/Inputs.md#Strict_Syntax).  
+If you expect students to use scientific notation for numbers, e.g. `3e4` (which means \(3\times 10^{4}\) ), then you may want to use the [option for strict syntax](../Authoring/Inputs.md#Strict_Syntax).
 
-Internally Maxima represents floats in binary, and so even simple calculations which would be exact in base ten (e.g. adding 0.16 to 0.12) might end up in a recurring decimal float which is not exactly equal to the result you would type in directly.  
+Internally Maxima represents floats in binary, and so even simple calculations which would be exact in base ten (e.g. adding 0.16 to 0.12) might end up in a recurring decimal float which is not exactly equal to the result you would type in directly.
 
 Try `452-4.52*10^2` in desktop Maxima, which is not zero, therefore `ATAlgEquiv(452,4.52*10^2)` fails. (Maxima 5.44.0, November 2022).  \(4.52\times 10^2\) ends up with recurring 9s when represented as a binary float, so it is not algebraically equivalent to the integer \(452\).
 
@@ -64,11 +64,11 @@ As another example, try `100.4-80.0;` in a desktop Maxima session.
 
 ## Maxima and floats with trailing zeros ##
 
-For its internal representation, Maxima always truncates trailing zeros from a floating point number.  For example, the Maxima expression `0.01000` will be converted internally to `0.01`.  Actually this is a byproduct of the process of converting a decimal input to an internal binary float, and back again.  Similarly, when a number is a "float" datatype, Maxima always prints at least one decimal digit to indicate the number is a float.  For example, the floating point representation of the number ten is \(10.0\).  This does _not_ indicate significant figures, rather it indicates data type.  In situations where the number of significant figures is crucial this is problematic.
+For its internal representation, Maxima always truncates trailing zeros from a floating point number.  For example, the Maxima expression `0.01000` will be converted internally to `0.01`.  Actually this is a byproduct of the process of converting a decimal input to an internal binary float, and back again.  Similarly, when a number is a "float" data type, Maxima always prints at least one decimal digit to indicate the number is a float.  For example, the floating point representation of the number ten is \(10.0\).  This does _not_ indicate significant figures, rather it indicates data type.  In situations where the number of significant figures is crucial this is problematic.
 
 Display of numbers in STACK is controlled with LaTeX, and the underlying LISP provides flexible ways to represent numbers.
 
-Note, that apart from the units input, all other input types truncate the display of unnecessary trailing zeros in floating point numbers, loosing information about significant figures.  So, when the student's answer is a floating point number, trailing zeros will not be displayed.  If you want to specifically test for significant figures, use the [units input type](../Topics/Units.md), with the teacher's answer having no units.  The units input type should display the same number of significant figures as typed in by the student.  
+Note, that apart from the units input, all other input types truncate the display of unnecessary trailing zeros in floating point numbers, loosing information about significant figures.  So, when the student's answer is a floating point number, trailing zeros will not be displayed.  If you want to specifically test for significant figures, use the [units input type](../Topics/Units.md), with the teacher's answer having no units.  The units input type should display the same number of significant figures as typed in by the student.
 
 ## Display of numbers with LaTeX ##
 
@@ -103,7 +103,7 @@ You can also force all integers to be displayed as floating point decimals or in
 | ----------- | ----------- | ---------------- | ----------------------------------------------------------------------------------------------
 | `"~,4f"`    | `0.12349`   | \(0.1235\)       |  Output four decimal places: floating point.
 |             | `0.12345`   | \(0.1234\)       |  Note the rounding.
-|             | `0.12`      | \(0.1200\)       |  
+|             | `0.12`      | \(0.1200\)       |
 | `"~,5e"`    | `100.34`    | \(1.00340e+2\)   |  Output five decimal places: scientific notation.
 | `"~:d"`     | `10000000`  | \(10,000,000\)   |  Separate decimal groups of three digits with commas.
 | `~r`        | `9`         | \(\mbox{nine}\)  |  Rhetoric.
@@ -136,7 +136,7 @@ If you separate decimal groups of digits with commas, e.g. if `stackfltfmt:"~:d"
 
 ## Notes about numerical rounding ##
 
-There are two ways to round numbers ending in a digit \(5\).  
+There are two ways to round numbers ending in a digit \(5\).
 
 * Always round up, so that \(0.5\rightarrow 1\), \(1.5 \rightarrow 2\), \(2.5 \rightarrow 3\) etc.
 * Another common system is to use ``Bankers' Rounding". Bankers Rounding is an algorithm for rounding quantities to integers, in which numbers which are equidistant from the two nearest integers are rounded to the nearest even integer. \(0.5\rightarrow 0\), \(1.5 \rightarrow 2\), \(2.5 \rightarrow 2\) etc.  The supposed advantage to bankers rounding is that in the limit it is unbiased, and so produces better results with some statistical processes that involve rounding.
@@ -158,8 +158,8 @@ The following commands which are relevant to manipulation of numbers are defined
 | `list_expression_numbers(ex)`   | Create a list with all parts for which `numberp(ex)=true`.
 | `coeff_list(ex,v)`              | This function takes an expression \(ex\) and returns a list of coefficients of \(v\).
 | `coeff_list_nz(ex,v)`           | This function takes an expression \(ex\) and returns a list of nonzero coefficients of \(v\).
-| `numabsolutep(sa,ta,tol)`       | Is \(sa\) within \(tol\) of \(ta\)? I.e. \( |sa-ta|<tol \)  
-| `numrelativep(sa,ta,tol)`       | Is \(sa\) within \(tol\times ta\) of \(ta\)? I.e. \( |sa-ta|<tol\times ta \).  
+| `numabsolutep(sa,ta,tol)`       | Is \(sa\) within \(tol\) of \(ta\)? I.e. \( |sa-ta|<tol \)
+| `numrelativep(sa,ta,tol)`       | Is \(sa\) within \(tol\times ta\) of \(ta\)? I.e. \( |sa-ta|<tol\times ta \).
 
 The following commands generate displayed forms of numbers.  These will not be manipulated further automatically, so you will need to use these at the last moment, e.g. only when generating the teacher's answer etc.
 
diff --git a/doc/en/CAS/Permutations.md b/doc/en/CAS/Permutations.md
index 2f18a6f70..f80ae2d6f 100644
--- a/doc/en/CAS/Permutations.md
+++ b/doc/en/CAS/Permutations.md
@@ -1,14 +1,14 @@
 # Writing a permutation as a product of disjoint cycles
 
 Let \[f= \left( \begin{array}{ccccccc} 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ 3 & 1 & 5 & 7 & 2 & 6 & 4 \end{array}\right)\]
- 
+
 In pure mathematics we might ask students to write a permutation such as this as a product of disjoint cycles.
 
 One way to do this is to expect students to write their answer as a list, including the one-cycles. e.g. the permutation \((1)(2 \: 3)\) is entered as `[[1],[2, 3]]`.
 
 This list can be turned into a set of lists, so that the order of disjoint cycles is not important.  However, we need to write each cycle in a particular way.  For example, we would want `[2, 3, 4]` and `[3, 4, 2]` to be considered as equivalent.
 
-One way to do this is to make sure the first element in the list is the minumum element in the list, by cycling through the list.  Essentially, we ensure each cycle is re-written in a definite form.  The following code does this for one cycle.  This function can be used in the question variables.
+One way to do this is to make sure the first element in the list is the minimum element in the list, by cycling through the list.  Essentially, we ensure each cycle is re-written in a definite form.  The following code does this for one cycle.  This function can be used in the question variables.
 
     /* Write a cycle with the smallest element at the front.  Gives a definite order. */
     perm_min_first(ex) := block(
@@ -23,4 +23,4 @@ Assume the student's answer `ans1` is entered as `[[1],[2, 3]]`.  In the feeback
 
 Then compare `setify(sa1)` with the teacher's answer (which needs to be processed in a similar way) using algebraic equivalence (quiet).
 
-This is a good example of where we do not have a specific data type and corresponding methods for equivalence, but the pre-processing of a student's answer will make sure we can establish the relevant equivalence.
\ No newline at end of file
+This is a good example of where we do not have a specific data type and corresponding methods for equivalence, but the pre-processing of a student's answer will make sure we can establish the relevant equivalence. 
\ No newline at end of file
diff --git a/doc/en/CAS/Predicate_functions.md b/doc/en/CAS/Predicate_functions.md
index aa52651d7..c0964a6f4 100644
--- a/doc/en/CAS/Predicate_functions.md
+++ b/doc/en/CAS/Predicate_functions.md
@@ -32,7 +32,7 @@ The following type predicates are defined by STACK.
 
 | Function                   | Predicate
 | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-| `variablep(ex)`            | Determines if \(ex\) is avariable, that is an atom but not a real numberm, \(i\) or a string.
+| `variablep(ex)`            | Determines if \(ex\) is a variable, that is an atom but not a real number, \(i\) or a string.
 | `equationp(ex)`            | Determines if \(ex\) is an equation.
 | `functionp(ex)`            | Determines if \(ex\) is a function definition, using the operator `:=`.
 | `inequalityp(ex)`          | Determines if \(ex\) is an inequality.
@@ -42,7 +42,7 @@ The following type predicates are defined by STACK.
 | `simp_integerp(ex)`        | Determines if \(ex\) is an integer when `simp:false`.
 | `real_numberp(ex)`         | Determines if \(ex\) is a real number.
 | `rational_numberp(ex)`     | Determines if \(ex\) is written as a fraction.  For a true mathematical rational number use `rational_numberp(ex) or simp_integerp(ex)`
-| `lowesttermsp(ex)`         | Determines if a fraction \(ex\) is in lowest terms.  
+| `lowesttermsp(ex)`         | Determines if a fraction \(ex\) is in lowest terms.
 | `complex_exponentialp(ex)` | Determines if \(ex\) is written in complex exponential form, \(r e^{i\theta} \).  Needs `simp:false`.
 | `imag_numberp(ex)`         | Determines if \(ex\) is a purely imaginary number.
 
diff --git a/doc/en/CAS/Random.md b/doc/en/CAS/Random.md
index e5c073076..facc7321f 100644
--- a/doc/en/CAS/Random.md
+++ b/doc/en/CAS/Random.md
@@ -4,7 +4,7 @@ STACK can generate structured random objects.  STACK provides a [Maxima](Maxima.
 
 STACK creates pseudo-random numbers from a definite seed.
 This ensures that when a particular student returns they see the same variant of the question.
-(Note to site maintainers: if you upgrade your Maxima version mid-way through an academic cycle, then there is no gurantee that the random numbers will remain the same.  It is unlikley Maxima will change its random number generation between versions, but if it important to you please check first!)
+(Note to site maintainers: if you upgrade your Maxima version mid-way through an academic cycle, then there is no gurantee that the random numbers will remain the same.  It is unlikely Maxima will change its random number generation between versions, but if it important to you please check first!)
 
 For the purposes of learning and teaching, we do not need an algorithm which is statistically perfect. We are much more interested in simplicity, efficiency and reproducibility across platforms. Hence, we adopt pseudo-random numbers.
 
@@ -117,7 +117,7 @@ Another option is to use `rand()` on a list of lists, allowing to group the info
     [p, g] : rand([["Mercury",3.61], ["Earth",9.81], ["Mars",3.75]]);
     ta:t*g/(4*%pi^2);
 
-Here, `rand()` will return one random list of the given lists, say `["Earth",9.81]`. The assigment `[p, g] : ["Earth",9.81]` then works as one would expect, namely just as `p : "Earth"; g : 9.81;` would.
+Here, `rand()` will return one random list of the given lists, say `["Earth",9.81]`. The assignment `[p, g] : ["Earth",9.81]` then works as one would expect, namely just as `p : "Earth"; g : 9.81;` would.
 
 ## Random objects satisfying a condition
 
diff --git a/doc/en/CAS/Real_Intervals.md b/doc/en/CAS/Real_Intervals.md
index f16137b11..f01e0673a 100644
--- a/doc/en/CAS/Real_Intervals.md
+++ b/doc/en/CAS/Real_Intervals.md
@@ -12,7 +12,7 @@ As arguments, the `%union` command can take both simple intervals and sets of di
 
     %union(oo(-inf,0),{1},oo(2,3));
 
-Similarly, STACK provides `%intersection` to represent an intersection of intervals (which the package `to_poly_solve` does not have). 
+Similarly, STACK provides `%intersection` to represent an intersection of intervals (which the package `to_poly_solve` does not have).
 
 Predicate functions
 
@@ -54,7 +54,7 @@ is displayed as \(x \not\in\{0\}\).
 
 Students must simply type `union` (not `%union`) etc.
 
-Validation of students' answer has a very loose sense of "type".  When we are checking the "type" of answer, if the teacher's answer is a "set" then the student's answer should also be a "set" (see `setp`).  If the teacher's answer is acually a set in the context where an interval should be considered valid, then the teacher's answer should be the inert function `%union`, e.g. `%union({1,2,3})`, to bump the type of the teacher's answer away from set and into `realset`.
+Validation of students' answer has a very loose sense of "type".  When we are checking the "type" of answer, if the teacher's answer is a "set" then the student's answer should also be a "set" (see `setp`).  If the teacher's answer is actually a set in the context where an interval should be considered valid, then the teacher's answer should be the inert function `%union`, e.g. `%union({1,2,3})`, to bump the type of the teacher's answer away from set and into `realset`.
 
 Validation does some simple checks, so that mal-formed intervals such as `oo(1)` and `oo(4,3)` are rejected as invalid.
 
diff --git a/doc/en/CAS/STACK-Maxima_sandbox.md b/doc/en/CAS/STACK-Maxima_sandbox.md
index d61101c9e..975c321f3 100644
--- a/doc/en/CAS/STACK-Maxima_sandbox.md
+++ b/doc/en/CAS/STACK-Maxima_sandbox.md
@@ -6,7 +6,7 @@ The first step is to install wxMaxima on your local machine (http://maxima.sourc
 
 ### Getting the STACK libraries
 
-You will need to download the STACK files onto your local machine.  Download all the STACK files from GitHub (git clone or as a .zip).  E.g. try `https://github.com/maths/moodle-qtype_stack/archive/master.zip` 
+You will need to download the STACK files onto your local machine.  Download all the STACK files from GitHub (git clone or as a .zip).  E.g. try `https://github.com/maths/moodle-qtype_stack/archive/master.zip`
 
 The only files you need to run the sandbox are contained within the directory
 
@@ -16,17 +16,17 @@ This directory also contains the wxMaxima file `sandbox.wmx` which is the "sandb
 
     stack/maxima/stackmaxima.mac
 
-Copy `sandbox.wmx` somewhere you can find it later and edit this file to reflect the location of the above file on your local machine.  
+Copy `sandbox.wmx` somewhere you can find it later and edit this file to reflect the location of the above file on your local machine.
 
-On a Microsoft operating system, if you place the all the files (i.e. clone or unzip the download) into 
+On a Microsoft operating system, if you place the all the files (i.e. clone or unzip the download) into
 
     c:/tmp/stackroot
 
-the `sandbox.wmx` should work without further adjustment.  
+the `sandbox.wmx` should work without further adjustment.
 
 Otherwise open `sandbox.wmx` with wxMaxima and follow the further instructions it contains to setup the path for Maxima.  __Note, the backslash character `\` is a control character so you will need to edit the path to replace the `\` with `/` in wxMaxima.__ Execute the sandbox file with wxMaxima when you have updated the settings with `cell > Evaluate all cells`.  If you see something like the following you have set this up correctly (version numbers will vary).
 
-    [ STACK-Maxima started, library version 2022022300 ] 
+    [ STACK-Maxima started, library version 2022022300 ]
 
 You can test this out by using, for example, the `rand()` function.
 
@@ -80,7 +80,7 @@ STACK turns off the traditional two-dimensional display, which we can turn back
 
     display2d:true;
 
-## Setting Maxima's Global Path (Microsoft) ###
+## Setting Maxima's Global Path (Microsoft)
 
 Setting the path in Maxima is a problem on a Microsoft platform.  Maxima does not deal well with spaces in filenames, for example.  The simplest solution is to create a directory
 
@@ -106,4 +106,4 @@ It is more important to match the version of the STACK code you downloaded from
 
     https://stack-demo.maths.ed.ac.uk/demo/question/type/stack/doc/doc.php/
 
-shows the version of the STACK code the demo site is running.
\ No newline at end of file
+shows the version of the STACK code the demo site is running. 
\ No newline at end of file
diff --git a/doc/en/CAS/Simplification.md b/doc/en/CAS/Simplification.md
index d574412b4..38afe46a3 100644
--- a/doc/en/CAS/Simplification.md
+++ b/doc/en/CAS/Simplification.md
@@ -25,7 +25,7 @@ To alter the order in STACK you can use the Maxima commands `orderless` and `ord
 
 See Maxima's documentation for more details.
 
-Only one `orderless` or `ordergreat` command can be issued in any session.  The last one encountered will be used and the others ignored.  
+Only one `orderless` or `ordergreat` command can be issued in any session.  The last one encountered will be used and the others ignored.
 No warnings or errors are issued if more than one is encountered.
 
 ## Logarithms to an arbitrary base
@@ -44,7 +44,7 @@ For example (with `simp:true` or `simp:false`)
 
 results in `p=lg(27, 3)`, and `q=3`.
 
-The algebraic equivalence function `algebraic_equivalence`, and so anything upon which it depends, will automatically remove logarithms to other bases.  
+The algebraic equivalence function `algebraic_equivalence`, and so anything upon which it depends, will automatically remove logarithms to other bases.
 This includes the answer tests as needed.
 
 ## Selective simplification {#selective-simplification}
@@ -52,7 +52,7 @@ This includes the answer tests as needed.
 The level of simplification performed by Maxima can be controlled by changing Maxima's global variable `simp`, e.g.
 
     simp:true
-    
+
 When `simp` is set to `false`, no simplification is performed and Maxima is quite happy to deal with an expression such as \(1+4\) without actually performing the addition.
 This is most useful for dealing with very elementary expressions, and for [showing working](../CAS/Matrix.md#Showing-working).
 
@@ -62,7 +62,7 @@ When `simp` is set to `false`, you can evaluate an expression with simplificatio
 
     simp:false;
     a:ev(1+1,simp);
-    
+
 will give \(a=2\).
 
 ### Within CASText (question text, general feedback, etc.)
@@ -93,7 +93,7 @@ This command sets the value of `simp` for this expression, and all others which
 
 ## Unary minus and simplification
 
-There are still some problems with the unary minus, e.g. sometimes we get the display \(4+(-3x)\) when we would actually like to always display as \(4-3x\).  
+There are still some problems with the unary minus, e.g. sometimes we get the display \(4+(-3x)\) when we would actually like to always display as \(4-3x\).
 This is a problem with the unary minus function `-(x)` as compared to binary infix subtraction `a-b`.
 
 To reproduce this problem type in the following into a Maxima session:
@@ -110,13 +110,13 @@ Notice the first subtraction is fine, but the second one is not.  To understand
     ?print(p);
     ((MPLUS) ((MEXPT) $Y 3) ((MMINUS) ((MTIMES) 2 ((MEXPT) $Y 2))) ((MTIMES) ((MMINUS) 8) $Y))
 
-In the structure of this expression the first negative coefficient is `-(2*y^2)` BUT the second is `-(8)*y`.   
-This again is a crucial but subtle difference!  
+In the structure of this expression the first negative coefficient is `-(2*y^2)` BUT the second is `-(8)*y`.
+This again is a crucial but subtle difference!
 To address this issue we have a function
 
     unary_minus_sort(p);
 
-which pulls "-" out the front in a specific situation: that of a product with a negative number at the front.  
+which pulls "-" out the front in a specific situation: that of a product with a negative number at the front.
 The result here is the anticipated `y^3-2*y^2-8*y`.
 
 Note that STACK's display functions automatically apply `unary_minus_sort(...)` to any expression being displayed.
@@ -161,7 +161,7 @@ Like `disp_parens`, STACK provides a function `disp_select` which highlights par
 
 STACK provides the function `remove_disp_select(ex)` to remove this inert display function.  The function `remove_disp(ex)` removes all inert display functions.
 
-When creating feedback it is often useful to select, and highlight, part of an expression.  STACK provides a function `select(p1, ex)` to do this.  The select function traverses the expression tree for `ex` and when it encounters a sub-tree for which the predicate `p1` is true it adds `disp_select` to the sub-tree and stops traversing any further down that sub-tree.  While nested `disp_select` are possible (and will dispaly multiple underlines: another reason for having underline) this particular function stops once `p1` is true.  You will need to build nested display by hand.
+When creating feedback it is often useful to select, and highlight, part of an expression.  STACK provides a function `select(p1, ex)` to do this.  The select function traverses the expression tree for `ex` and when it encounters a sub-tree for which the predicate `p1` is true it adds `disp_select` to the sub-tree and stops traversing any further down that sub-tree.  While nested `disp_select` are possible (and will display multiple underlines: another reason for having underline) this particular function stops once `p1` is true.  You will need to build nested display by hand.
 
 For example, to select all the integers in an expression you can use the predicate `integerp` and `select(integerp, 1+x+0.5*x^2)` gives \(\color{red}{\underline{1}}+x+0.5\cdot x^{\color{red}{\underline{2}}}\).
 
@@ -240,7 +240,7 @@ To create the binomial coefficients
 
 ## Surds
 
-Imagine you would like the student to expand out \( (\sqrt{5}-2)(\sqrt{5}+4)=2\sqrt{5}-3 \). 
+Imagine you would like the student to expand out \( (\sqrt{5}-2)(\sqrt{5}+4)=2\sqrt{5}-3 \).
 There are two tests you probably want to apply to the student's answer.
 
 1. Algebraic equivalence with the correct answer: use `ATAlgEquiv`.
diff --git a/doc/en/CAS/Validator.md b/doc/en/CAS/Validator.md
index 937f6ae0b..a58e3f19d 100644
--- a/doc/en/CAS/Validator.md
+++ b/doc/en/CAS/Validator.md
@@ -33,7 +33,7 @@ A single validator function can be re-used on multiple inputs within a single qu
 
 ## Combining validators
 
-If you wish to test for a number of separate properties then it is probably best to create separate functions for each poperty and combine them into a single validator.
+If you wish to test for a number of separate properties then it is probably best to create separate functions for each property and combine them into a single validator.
 
 For example, imagine you would like the following:
 
@@ -45,7 +45,7 @@ E.g. `[x^2=1, y=1, x+z=1]` is a valid answer.  `[x^2+5, y=1]` is invalid (for tw
 
 Functions which establish these properties are:
 
-    /* Define validator fuctions separately. */
+    /* Define validator functions separately. */
     validate_islist(ex) := if listp(ex) then "" else "Your answer must be a list.";
     validate_allequations(ex) := if all_listp(equationp, ex) then "" else "All elements of your answer should be equations.";
     validate_checklen(ex) :=  if ev(is(length(ex)=3),simp) then "" else "Your list must have 3 elements.";
diff --git a/doc/en/CAS/index.md b/doc/en/CAS/index.md
index 3b2e580fa..4a97786ff 100644
--- a/doc/en/CAS/index.md
+++ b/doc/en/CAS/index.md
@@ -1,6 +1,6 @@
 # Maxima and computer algebra use in STACK
 
-STACK uses the computer algebra system (CAS) [Maxima](Maxima.md) and a graphical desktop interface like [wxMaxima](http://andrejv.github.com/wxmaxima/) can be helpful for ofline editing, including a [STACK-Maxima sandbox](STACK-Maxima_sandbox.md) for testing question code on the desktop.
+STACK uses the computer algebra system (CAS) [Maxima](Maxima.md) and a graphical desktop interface like [wxMaxima](http://andrejv.github.com/wxmaxima/) can be helpful for off line editing, including a [STACK-Maxima sandbox](STACK-Maxima_sandbox.md) for testing question code on the desktop.
 
 Computer algebra systems are most often designed for either the research mathematician, or the student _to do calculations_. For the purposes of assessment our calculation _establish some relevant properties_ of the students' answers.  Establishing properties in this way, and on the basis of this creating outcomes such as feedback, is something particular to assessment systems. Such properties include things like
 
diff --git a/doc/en/Developer/Development_track.md b/doc/en/Developer/Development_track.md
index 21aabc51b..03c123a9e 100644
--- a/doc/en/Developer/Development_track.md
+++ b/doc/en/Developer/Development_track.md
@@ -7,18 +7,21 @@ past development history is documented on [Development history](Development_hist
 
 This version will require moodle 4.0+, and will no longer support Moodle 3.x (which ends its general support on 14 November 2022, and security support ends on 11 December 2023.)
 
-Todo: 
+Todo:
 
 1. Change 'core/event' to 'core_filters/events' in input.js and stackjsvle.js.
 2. Strip out parallel DB support in reporting etc.  Search for `stack_determine_moodle_version()`
 3. Bring the API into the core of STACK for longer term support, and better support for ILIAS.
 4. Major code tidy: Moodle code style now requires (i) short forms of arrays, i.e. `[]` not `array()`, and (ii) commas at the end of all list items.
+5. Fix markdown problems. See issue #420.
+6. Error messages: use caserror.class more fully to use user information to target error messages.
+7. Remove all "cte" code from Maxima - mostly install.
 
 ## Version 4.5.0
 
 Please note, this is the _last_ version of STACK which will support Moodle 3.x.
 
-1. Refactor the healthcheck scripts, especially to make unicode requirements for maxima more prominent.
+1. Re-factor the healthcheck scripts, especially to make unicode requirements for maxima more prominent.
 2. Shape of brackets surrounding matrix/var matrix input types now matches question level option for matrix parentheses.  (TODO: possible option to change shape at the input level?)
 3. Allow users to [systematically deploy](../CAS/Systematic_deployment.md) all variants of a question in a simple manner.
 4. Tag inputs with 'aria-live' is 'assertive' for better screen reader support.
@@ -28,20 +31,14 @@ Please note, this is the _last_ version of STACK which will support Moodle 3.x.
 8. Add in an option `margin` to control margins around STACK-generated plots.
 9. Add in better support for proof as [Parson's problems](../Authoring/Parsons.md).
 
-TODO: 
-
-1. Fix markdown problems. See issue #420.
-2. Error messages: use caserror.class more fully to use user information to target error messages.
-3. Remove all "cte" code from Maxima - mostly install.
-
 ## Parson's block development track
 
 Essential (v 4.5.0)
 
 1. Add in an option "fixed".  When we have "submit all and finish" we don't want to allow users to then drag things.  This is an edge case for after the quiz.  I think we can achive this by adding in an argument to the JSON in the student's input "fixed", and this will get sent to the block.  We can talk about this.
 2. Polish up the "use once" or "clone" strings.
-3. Use syntax hint to set up a non-empty starting point....
-4. Check sortable for keyboard accessibility (SM: Not build in to Sortable currently: https://github.com/SortableJS/Sortable/issues/1951; however, it looks like it is do-able with some work https://robbymacdonell.medium.com/refactoring-a-sortable-list-for-keyboard-accessibility-2176b34a07f4) 
+3. Use syntax hint to set up a non-empty starting point.
+4. Check sortable for keyboard accessibility (SM: Not built-in to Sortable currently: https://github.com/SortableJS/Sortable/issues/1951; however, it looks like it is do-able with some work https://robbymacdonell.medium.com/refactoring-a-sortable-list-for-keyboard-accessibility-2176b34a07f4)
 5. CSS styling fix for automated feedback
 
 Later
@@ -50,7 +47,7 @@ Later
 2. Different proof types -- iff, induction, etc. how do we indicate the different scaffolding for this?
 2. Create templates from the start for different proof types
 4. Restrict blocks to fixed number of steps
-5. Other draggable arrangements, e.g. fill in a 2*2 grid (for matching problems)
+5. Other arrangements, e.g. fill in a 2*2 grid (for matching problems)
    Nested lists (flat list vs. nested/tree)
 6. Allow student to select proof style (e.g. iff, contradiction) and pre-structure answer list accordingly
 7. Allow some strings in the correct answer to be optional. Allow authors to input a weight for each item and use weighted D-L distance, e.g., weight of 0 indicates that a step is not required, but will not be considered incorrect if included.
@@ -58,6 +55,7 @@ Later
 9. Allow students to mark items (e.g. as used or unneeded) or tick used items
 10. Confirmation for delete all?
 11. Alternative styling/signalling for clone mode?
+12. Better support (and documentation) for bespoke grading functions.
 
 
 ## For "inputs 2"?
diff --git a/doc/en/Installation/Release_notes_4_4_x.md b/doc/en/Installation/Release_notes_4_4_x.md
index 66e058b8b..1aeb277cb 100644
--- a/doc/en/Installation/Release_notes_4_4_x.md
+++ b/doc/en/Installation/Release_notes_4_4_x.md
@@ -26,7 +26,7 @@ Solution: Don't forbid input of brackets!
 
 ### Issue: when selecting function names from a list.
 
-When using something like 
+When using something like
 
     func:rand([sin,cos,exp,ln]);
     is(equal(func,ln));
@@ -35,7 +35,7 @@ now returns unknown. Used to return true/false.
 
 Solution: First generate a random integer. Set `func` based on that, and test the value of the integer. (Not as neat!)
 
-### Issue: MathJax 
+### Issue: MathJax
 
 Mathjax no longer likes   `\begin{pmatrix}{@xx@}\\{@yy@}\end{pmatrix}` in castext.
 
diff --git a/doc/en/Installation/Testing_installation.md b/doc/en/Installation/Testing_installation.md
index f1d28ec7e..48a6ef133 100644
--- a/doc/en/Installation/Testing_installation.md
+++ b/doc/en/Installation/Testing_installation.md
@@ -4,7 +4,7 @@ It is important to confirm that STACK has been installed correctly, and that it
 
 ## STACK configuration page
 
-STACK provides a number of options.  To set these you must login as the Moodle site Administrator.  Navigate to 
+STACK provides a number of options.  To set these you must login as the Moodle site Administrator.  Navigate to
 
     Site administration -> Plugins -> Question Types -> STACK
 
@@ -12,10 +12,10 @@ STACK provides a number of options.  To set these you must login as the Moodle s
 
 To confirm if the PHP scripts are connecting to Maxima navigate to the _STACK configuration page_ (see above).  Choose the link to the "healthcheck script".
 
-The healthcheck script checks the following. 
+The healthcheck script checks the following.
 
 * Check LaTeX is being converted correctly?  Check [MathJax](Mathjax.md) or another LaTeX converter.
-* Can PHP call external applications?  No, then change PHP settings. 
+* Can PHP call external applications?  No, then change PHP settings.
 * Can PHP call Maxima? No, then see below.
 * Does Maxima support unicode?  Distributed versions of Maxima do (as of July 2023) but if you compile Maxima from source then you must include unicode support.
 * Graph plotting. Are auto-generated plots being created correctly?  There should be two different graphs.  If not, check the gnuplot settings, and directory permissions.
@@ -39,15 +39,15 @@ If you wish to subvert this process you will need to alter the source code of ST
 
 # Caching CAS output
 
-By default, the interactions with the CAS are cached.  You can connect freshly to the CAS each time, which is useful for  debugging, and this option is available on the STACK configuration page.  To clear the cache, click the button on the healthcheck script. 
+By default, the interactions with the CAS are cached.  You can connect freshly to the CAS each time, which is useful for  debugging, and this option is available on the STACK configuration page.  To clear the cache, click the button on the healthcheck script.
 
-## Optimizing Maxima 
+## Optimizing Maxima
 
-Maxima is the rate-determining step in performance to STACK. Once you have the STACK question type working with a direct connection to the CAS, then you should consider optimizing the  performance of Maxima.  See the page dedicated to [optimizing Maxima](Optimising_Maxima.md) 
+Maxima is the rate-determining step in performance to STACK. Once you have the STACK question type working with a direct connection to the CAS, then you should consider optimizing the  performance of Maxima.  See the page dedicated to [optimizing Maxima](Optimising_Maxima.md)
 
 ## CAS Chat
 
-At any stage you can evaluate a fragment of CASText by using the CASChat script.  There is a link from the STACK configuration page. 
+At any stage you can evaluate a fragment of CASText by using the CASChat script.  There is a link from the STACK configuration page.
 
 ## Testing your questions when you upgrade
 
@@ -57,9 +57,9 @@ Please check the [release notes](../Developer/Development_history.md) carefully.
 
 Whenever you upgrade to a new version of the STACK plugin, it is a really good idea to run all
 of the [question tests](../Authoring/Testing.md) to be sure that the behaviour of STACK has not
-changed in a way that breaks any of your questions. To do this, go to 
+changed in a way that breaks any of your questions. To do this, go to
 
-    Site administration -> Plugins -> Question types -> STACK 
+    Site administration -> Plugins -> Question types -> STACK
 
 and follow the "run the question tests in bulk script" link.
 
@@ -93,15 +93,15 @@ To set these you must login as the Moodle site Administrator.  Take note of your
     qtype_stack | castimeout = 100
     qtype_stack | maximacommand =
     qtype_stack | maximacommandopt =
-    qtype_stack | maximalibraries = 
+    qtype_stack | maximalibraries =
 
 Note that the `maximacommand`, `maximacommandopt` and `maximalibraries` should be empty boxes.
 
-The `castimeout` of 100s is excessive. However, the very first time Maxima is called on a server it internally compiles a lot of LISP sourcecode.  This can take a surprisingly long time!
+The `castimeout` of 100s is excessive. However, the very first time Maxima is called on a server it internally compiles a lot of LISP source code.  This can take a surprisingly long time!
 
-### 3. GOAL: Reduce timeout and check Maxima libraies.
+### 3. GOAL: Reduce timeout and check Maxima libraries.
 
-Now we need to back away gently from the above raw confuration, back towards the defaults/production settings.
+Now we need to back away gently from the above raw configuration, back towards the defaults/production settings.
 
     qtype_stack | castimeout = 10
     qtype_stack | maximalibraries = stats, distrib, descriptive, simplex
@@ -114,7 +114,7 @@ If you want to choose a specific version of Maxima now is the time to do so by s
 
     qtype_stack | maximaversion
 
-from the dropdown.  Part of the healthcheck script will tell you which version you have on your server or use `maxima --list-avail` on the command line.  If your version does not appear on the dropdown (and it won't if you compiled Maxima from source) then set `maximacommand` to be the command you need to type.  E.g. if you use `maxima --use-version=5.42.1` on the command line then 
+from the dropdown.  Part of the healthcheck script will tell you which version you have on your server or use `maxima --list-avail` on the command line.  If your version does not appear on the dropdown (and it won't if you compiled Maxima from source) then set `maximacommand` to be the command you need to type.  E.g. if you use `maxima --use-version=5.42.1` on the command line then
 
     qtype_stack | maximacommand = maxima --use-version=5.42.1
 
@@ -162,4 +162,4 @@ The very last step is to use the CAS cache.
 
     qtype_stack | casresultscache = Cache in the database
 
-This should be a working server, using the optimised image.  Please consider using the Maxima Pool for production sites, putting Maxima onto another server competely.
\ No newline at end of file
+This should be a working server, using the optimised image.  Please consider using the Maxima Pool for production sites, putting Maxima onto another server completely. 
\ No newline at end of file
diff --git a/doc/en/Installation/index.md b/doc/en/Installation/index.md
index 18c97db74..de383fb21 100644
--- a/doc/en/Installation/index.md
+++ b/doc/en/Installation/index.md
@@ -2,7 +2,7 @@
 
 STACK is being used live at many institutions, including the University of Edinburgh, the UK Open University, Aalto, Loughborough University, and the University of Birmingham in the UK.
 
-We appreciate some people perfer hosted services as an alterntaive to running their own server. We are pleased to work with EDINA at the University of Edinburgh as a [recommended hosting partner](https://stack.edina.ac.uk/).
+We appreciate some people prefer hosted services as an alternative to running their own server. We are pleased to work with EDINA at the University of Edinburgh as a [recommended hosting partner](https://stack.edina.ac.uk/).
 
 STACK is designed to be used on a Linux-based server.  The Windows/MS option exists to help teachers author questions offline, and for demonstration and development.  However, for demonstration, development and offline use we strongly recommend using VirtualBox instead of the Windows port.  Note also that support for the optimized Maxima image is not available on Windows platforms, which is a substantial performance improvement.
 
@@ -43,13 +43,13 @@ to `filter_mathjaxloader | mathjaxconfig` in the filter settings: Dashboard > Si
 
 Ensure gcc, gnuplot and [Maxima](http://maxima.sourceforge.net) are installed on your server.  Currently Maxima 5.38.1 to 5.47.0 are supported.  Please contact the developers to request support for other versions.  (Newer versions will be supported, and prompts to test them are welcome.)  We currently recommend that you use any version of Maxima after 5.43.0.
 
-Maxima can be installed via a package manager on most Linux distributions (e.g. `sudo apt-get install maxima` on Debian/Ubuntu), [downloaded](http://maxima.sourceforge.net/download.html) as a self-contained installer program for Windows, or [compiled from source](Maxima.md).  Please make sure you also have `maxima-share` installed.  (This is automatically installed on some distros, but not others.)
+Maxima can be installed via a package manager on most Linux distributions (e.g. `sudo apt-get install maxima` on Debian/Ubuntu), [downloaded](http://maxima.sourceforge.net/download.html) as a self-contained installer program for Windows, or [compiled from source](Maxima.md).  Please make sure you also have `maxima-share` installed.  (This is automatically installed on some distributions, but not others.)
 
 To check your version of maxima, run `maxima --version`.  If Moodle is set up using Apache, STACK will run maxima through the Apache user (`www-data/apache2`).  To check that this works, run maxima as the apache user (e.g. `sudo -u www-data maxima`).  Later versions of maxima create a cache and thus the executing user needs to have write access to a temporary folder, see [#731](https://github.com/maths/moodle-qtype_stack/issues/731) for more details and troubleshooting.
 
 Alternatively, Maxima can also be run on a separate server via [GoeMaxima](https://github.com/mathinstitut/goemaxima) or [MaximaPool](https://github.com/maths/stack_util_maximapool).
 
-Please note 
+Please note
 
 * Please avoid versions 5.37.x which are known to have a minor bug which affects STACK. In particular with `simp:false`, \(s^{-1}\) is transformed into \(1/s\).  This apparently minor change makes it impossible to distinguish between the two forms.  This causes all sorts of problems.  Do not use Maxima 5.37.1 to 5.37.3.
 * Older versions of Maxima:  in particular, Maxima 5.23.2 has some differences which result in \(1/\sqrt{x} \neq \sqrt{1/x}\), and similar problems.  This means that we have an inconsistency between questions between versions of maxima.   Of course, we can argue about which values of \(x\) make \(1/\sqrt{x} = \sqrt{1/x}\), but currently the unit tests and assumption is that these expressions should be considered to be algebraically equivalent!   So, older versions of Maxima are not supported for a reason.  Please test thoroughly if you try to use an older version, and expect some errors in the mathematical parts of the code.
@@ -61,21 +61,21 @@ Instructions for installing a more recent version of Maxima on CentOS 6 are avai
 
 STACK requires these.
 
-1. Obtain Deferred feedback with explicit validation behaviour code. You can [download the zip file](https://github.com/maths/moodle-qbehaviour_dfexplicitvaildate/zipball/master), unzip it, and place it in the directory `moodle/question/behaviour/dfexplicitvaildate`. (You will need to rename the directory `moodle-qbehaviour_dfexplicitvaildate -> dfexplicitvaildate`.) 
+1. Obtain Deferred feedback with explicit validation behaviour code. You can [download the zip file](https://github.com/maths/moodle-qbehaviour_dfexplicitvaildate/zipball/master), unzip it, and place it in the directory `moodle/question/behaviour/dfexplicitvaildate`. (You will need to rename the directory `moodle-qbehaviour_dfexplicitvaildate -> dfexplicitvaildate`.)
 
-Alternatively, get the code using git by running the following command in the top level folder of your Moodle install: 
+Alternatively, get the code using git by running the following command in the top level folder of your Moodle install:
 
         git clone https://github.com/maths/moodle-qbehaviour_dfexplicitvaildate.git question/behaviour/dfexplicitvaildate
 
-2. Obtain Deferred feedback with CBM and explicit validation behaviour code. You can [download the zip file](https://github.com/maths/moodle-qbehaviour_dfcbmexplicitvaildate/zipball/master), unzip it, and place it in the directory `moodle/question/behaviour/dfcbmexplicitvaildate`. (You will need to rename the directory `moodle-qbehaviour_dfcbmexplicitvaildate -> dfcbmexplicitvaildate`.) 
+2. Obtain Deferred feedback with CBM and explicit validation behaviour code. You can [download the zip file](https://github.com/maths/moodle-qbehaviour_dfcbmexplicitvaildate/zipball/master), unzip it, and place it in the directory `moodle/question/behaviour/dfcbmexplicitvaildate`. (You will need to rename the directory `moodle-qbehaviour_dfcbmexplicitvaildate -> dfcbmexplicitvaildate`.)
 
-Alternatively, get the code using git by running the following command in the top level folder of your Moodle install: 
+Alternatively, get the code using git by running the following command in the top level folder of your Moodle install:
 
         git clone https://github.com/maths/moodle-qbehaviour_dfcbmexplicitvaildate.git question/behaviour/dfcbmexplicitvaildate
-2. Obtain adaptivemutlipart behaviour code. You can [download the zip file](https://github.com/maths/moodle-qbehaviour_adaptivemultipart/zipball/master), unzip it, and place it in the directory `moodle/question/behaviour/adaptivemultipart`. (You will need to rename the directory `moodle-qbehaviour_adaptivemultipart  -> adaptivemultipart`.) 
+2. Obtain adaptivemutlipart behaviour code. You can [download the zip file](https://github.com/maths/moodle-qbehaviour_adaptivemultipart/zipball/master), unzip it, and place it in the directory `moodle/question/behaviour/adaptivemultipart`. (You will need to rename the directory `moodle-qbehaviour_adaptivemultipart  -> adaptivemultipart`.)
+
+Alternatively, get the code using git by running the following command in the top level folder of your Moodle install:
 
-Alternatively, get the code using git by running the following command in the top level folder of your Moodle install: 
-    
         git clone https://github.com/maths/moodle-qbehaviour_adaptivemultipart.git question/behaviour/adaptivemultipart
 3. Login to Moodle as the admin user and click on Notifications in the Site Administration panel.
 
@@ -83,10 +83,10 @@ Alternatively, get the code using git by running the following command in the to
 
 STACK is a question type for the Moodle quiz.
 
-1. Obtain the code. You can [download the zip file](https://github.com/maths/moodle-qtype_stack/zipball/master), unzip it, and place it in the directory `moodle/question/type/stack`. (You will need to rename the directory `moodle-qtype_stack -> stack`.) 
+1. Obtain the code. You can [download the zip file](https://github.com/maths/moodle-qtype_stack/zipball/master), unzip it, and place it in the directory `moodle/question/type/stack`. (You will need to rename the directory `moodle-qtype_stack -> stack`.)
+
+    Alternatively, get the code using git by running the following command in the top level folder of your Moodle install:
 
-    Alternatively, get the code using git by running the following command in the top level folder of your Moodle install: 
-    
         git clone https://github.com/maths/moodle-qtype_stack.git question/type/stack
 2. Login to Moodle as the admin user and click on Notifications in the Site Administration panel.
 3. As the admin user, navigate to `Home > Site administration > Plugins > Question types > STACK`.  Please choose and save the appropriate options.
@@ -162,7 +162,7 @@ If STACK is already installed, as described above, it can be updated via git, li
 
 2. Then login as admin in your moodle and update the database.
 
-3. As admin user, navigate to yourmoodle/admin/settings.php?section=qtypesettingstack 
+3. As admin user, navigate to yourmoodle/admin/settings.php?section=qtypesettingstack
 
 4. Check for the correct maxima version.
 
diff --git a/doc/en/Maintaining/index.md b/doc/en/Maintaining/index.md
index 1df1bf288..cd310d6c4 100644
--- a/doc/en/Maintaining/index.md
+++ b/doc/en/Maintaining/index.md
@@ -1,14 +1,16 @@
 # Maintaining questions and question banks
 
-This section of the documentation provides information on testing questions and maintaining question banks for the long term.  Access to functions related to maintaining STACK questions is through the "adminui" page
+This section of the documentation provides information on testing questions and maintaining question banks for the long term.  Access to functions related to testing STACK questions and maintaining question banks for the long term is through the "adminui" page
 
     [...]/question/type/stack/adminui/index.php
 
-(or available from the qtype_stack plugin setting page).  To make use of these tools (in Moodle) users require the capability `qtype/stack:usediagnostictools` via Moodle's capability system.  We stronly recommend anyone who regularly writes STACK questions across more than one Moodle course be given this capability.  It enables the following:
+(or available from the qtype_stack plugin setting page).  To make use of these tools (in Moodle) users require the capability `qtype/stack:usediagnostictools` via Moodle's capability system.  We strongly recommend anyone who regularly writes STACK questions across more than one Moodle course be given this capability.  It enables the following:
 
-* Bulk testing of questions.
+* Bulk testing of questions, and efficient follow-up via direct links to the "STACK question dashboard" for questions of interest
 * Identifying STACK questions using particular blocks, e.g. the "todo" block, or includes.
 * Bulk change of the default settings.
+* Direct connection to Maxima (with normal teacher privileges in place) through a "Chat" script
+* Ability to view unit test results for STACK answer tests online, which acts as comprehensive documentation for the intended behaviour, with commentary.
 
 If your institution restricts site admin status, then this capability will allow a subset of users to access these functions. If it is not possible to get this capability, then Moodle site administrators will need to run the tests themselves and give you the results.
 
diff --git a/doc/en/Moodle/Import_Export.md b/doc/en/Moodle/Import_Export.md
index a1afebb0a..2cf8f88f4 100644
--- a/doc/en/Moodle/Import_Export.md
+++ b/doc/en/Moodle/Import_Export.md
@@ -16,7 +16,7 @@ There are two ways to export STACK questions.
 
 1. The normal Moodle procedure is to export whole category of questions at one time through the Moodle question bank.  To export a selection of questions, you need to move them into a separate category.  This can be any mix of STACK and other Moodle questions.  You must choose "Moodle XML format" as the file format.
 2. To export a single STACK question as "Moodle XML format".
-   1. Preview the question.  
+   1. Preview the question.
    2. Follow the link to "Question tests & deployed variants".
    3. Export this question.
 
@@ -26,14 +26,14 @@ There are two ways to export STACK questions.
 
 STACK 4.0 has one important change in the question authoring.  [CASText](../Authoring/CASText.md) now uses `{@...@}` in include mathematics in the text.  The change from `@...@` to `{@...@}` gives us matching parentheses to parse, which is much better.  The `{..}` will not break LaTeX.
 
-You will need to update all your existing questions which include CAS calculations. This includes all fields, e.g. in the feedback as well.  To help with this process we have an automatic conversion script.  As an admin user navigate to 
+You will need to update all your existing questions which include CAS calculations. This includes all fields, e.g. in the feedback as well.  To help with this process we have an automatic conversion script.  As an admin user navigate to
 
-    Site administration -> 
+    Site administration ->
     Plugins ->
     Question Types ->
     STACK
 
-Then choose the link "The fix maths delimiters script". 
+Then choose the link "The fix maths delimiters script".
 
 ## Importing STACK 2 questions
 
@@ -56,4 +56,4 @@ There have been a number of changes between STACK 2 and STACK 3.  These are deta
   * the options which ask the student to verify and to show validation feedback.
   * question level penalty option.
 * Questions with a single potential response tree import with the PRT feedback in the specific feedback slot, not in the question text.  We envisage this will enable single part questions to respect a wider variety of Moodle question behaviours.
-* When importing question tests, the new testing mechanism in STACK 3 enables the teacher to specify a score and penalty, not just an answer note.  Since we have to set defaults on import, most question tests now fail and this information will need to be added by hand.  A good opportunity to confirm questions have imported correctly.....
+* When importing question tests, the new testing mechanism in STACK 3 enables the teacher to specify a score and penalty, not just an answer note.  Since we have to set defaults on import, most question tests now fail and this information will need to be added by hand.  A good opportunity to confirm questions have imported correctly.
diff --git a/doc/en/Moodle/Semi-automatic_Marking.md b/doc/en/Moodle/Semi-automatic_Marking.md
index e32c79991..bd544d632 100644
--- a/doc/en/Moodle/Semi-automatic_Marking.md
+++ b/doc/en/Moodle/Semi-automatic_Marking.md
@@ -13,6 +13,6 @@ STACK provides the "notes" [input type](../Authoring/Inputs.md).  There are some
 
 ## Manual grading.
 
-The notes input has a special extra option `manualgraded`, and the default option value is `manualgraded:false`.  If you specify `manualgraded:true` then the _whole STACK quesion_ will require manual grading!
+The notes input has a special extra option `manualgraded`, and the default option value is `manualgraded:false`.  If you specify `manualgraded:true` then the _whole STACK question_ will require manual grading!
 
-There really is no way to mix automatic and manually graded parts of a question. Therefore, if you want automatic and manual marking you must have separate questions.
\ No newline at end of file
+There really is no way to mix automatic and manually graded parts of a question. Therefore, if you want automatic and manual marking you must have separate questions. 
\ No newline at end of file
diff --git a/doc/en/Moodle/index.md b/doc/en/Moodle/index.md
index df66c5fe8..dc25ff213 100644
--- a/doc/en/Moodle/index.md
+++ b/doc/en/Moodle/index.md
@@ -1,6 +1,6 @@
 # STACK within the Moodle VLE.
 
-This page contains useful information about using STACK within the Moodle VLE.
+This section contains useful information about using STACK within the Moodle VLE.
 
 * [Finding the question bank](Question_bank.md),
 * [Creating a quiz](../AbInitio/Authoring_quick_start_8.md),
diff --git a/doc/en/Plots/Plots.md b/doc/en/Plots/Plots.md
index 572444eba..b4361fa17 100644
--- a/doc/en/Plots/Plots.md
+++ b/doc/en/Plots/Plots.md
@@ -2,7 +2,7 @@
 
 In STACK, the `plot` command has been defined to be a wrapper for Maxima's `plot2d` command.  The wrapper makes sure that an image file is given an appropriate name, file location, and that Maxima returns a URL to the user giving the image.  Not all of the features of `plot2d` are available through `plot`.
 
-For example, 
+For example,
 
 1. Try the following in a castext field. `{@plot(x^2,[x,-1,1])@}`.
 2. You can add a second variable to control the range of the y-axes. `plot(x^2,[x,-1,1],[y,0,2])`.
@@ -61,7 +61,7 @@ If you would like an expression as part of this then try
 
 Note, you cannot put language strings directly into the alt-text.  E.g. the following will not be translated.
 
-    {@plot(x^2,[x,-2,2],[alt,"[[lang code='en,other']]A quadratic curve[[/lang]][[lang code='no']]En kvadratisk kurve[[/lang]]"])@}  
+    {@plot(x^2,[x,-2,2],[alt,"[[lang code='en,other']]A quadratic curve[[/lang]][[lang code='no']]En kvadratisk kurve[[/lang]]"])@}
 
 You can define a castext element in the question variables which does get translated, e.g.
 
@@ -126,7 +126,7 @@ Now use:
 
     {@plot(pg2(x), [x,(x0-5),(x0+5)], [y,-10,10], [legend,false])@}
 
-A further example of a step functio:
+A further example of a step function:
 
     step_fn(x,x0) := unit_step(x-x0-1/2) - unit_step(x-x0+1/2) + und*kron_delta(x,x0+1/2)+ und*kron_delta(x,x0-1/2);
     p1:sum(step_fn(x,2*k),k,-3,3);
diff --git a/doc/en/Proof/Proof_CAS_library.md b/doc/en/Proof/Proof_CAS_library.md
index 80f0713e1..f9bf0ea0f 100644
--- a/doc/en/Proof/Proof_CAS_library.md
+++ b/doc/en/Proof/Proof_CAS_library.md
@@ -58,7 +58,7 @@ Note that the variable `proof_steps` is a _list_ of lists:  `[ ["key", "step", (
 2. The `key` can be an integer position in the proof_steps, a string `key`, or a string.
   * Using integers: `proof_iff(proof(1,2,3,4,5),proof(6,7,8,9,10,11))`;
   * Using keys: `proof_iff(proof("assodd","defn_odd","alg_odd","def_M_odd","conc_odd"),proof("contrapos","assnotodd","even","alg_even","def_M_even","conc_even"))`
-3. The `proof_steps` list can contain an optional string argument `"comment"`.  This string can be used to store justification, explaination and narative.  Some display functions use this argument, when it exists.  To prume out the comments use `proof_steps_prune(proof_steps)` as an argument to the display function.
+3. The `proof_steps` list can contain an optional string argument `"comment"`.  This string can be used to store justification, explanation and narrative.  Some display functions use this argument, when it exists.  To prune out the comments use `proof_steps_prune(proof_steps)` as an argument to the display function.
 4. Note that the backslash must be protected when defining these strings.
 5. The strings can contain HTML, including `<img>` tags for including images within draggable elements.
 
diff --git a/doc/en/Proof/Proof_assessment.md b/doc/en/Proof/Proof_assessment.md
index 0c4e6259f..0c2be8096 100644
--- a/doc/en/Proof/Proof_assessment.md
+++ b/doc/en/Proof/Proof_assessment.md
@@ -46,5 +46,3 @@ To display feedback use `{@proof_assessment_display(saa, proof_steps)@}` in a PR
 In addition to the automatic feedback, or as an alternative, a teacher can check other properties and define feedback as required.
 
 E.g. a teacher might want to provide feedback such as _"It makes no sense to use \(M\) before it is defined!"_.
-
-TODO: examples of how to do this, and general tools to support bespoke assessment.... 
\ No newline at end of file
diff --git a/doc/en/Proof/index.md b/doc/en/Proof/index.md
index f2626c2b4..c64feb692 100644
--- a/doc/en/Proof/index.md
+++ b/doc/en/Proof/index.md
@@ -1,4 +1,4 @@
-# Support for proof and recepies in STACK
+# Support for proof in STACK
 
 In STACK the basic assumption is that a student's answer will be a mathematical expression, e.g. a polynomial or an equation.  While the facilities for assessing a student's free-form proof is limited (in any online assessment system), teachers can create materials for assessing students' understanding of proof in general, and of particular mathematical proofs.
 
@@ -23,7 +23,7 @@ Colleagues assessing proof might also consider [semi-automatic marking](../Moodl
 Mathematical writing, especially for students, commonly takes two forms.
 
 1. A mathematical proof, which is a deductive justification of a claim.  A proof is a "checkable record of reasoning".
-2. A mathematical recepie, which is a set of instructions for carrying out a procedure.
+2. A mathematical recipe, which is a set of instructions for carrying out a procedure.
 
 ## Presentation of proof
 
@@ -47,13 +47,9 @@ By separating out these issues we provide more control, and wider opportunities
 Consider the following theorem:  \(\sum_{k=1}^n (2k-1) = 1+3+5+\cdots + (2n-1) = n^2\).
 A traditional proof is shown below. This proof was published by DeMorgan in 1838.  According to Cajori (1918) this is the first use of the name "mathematical induction", although DeMorgan calls it "successive induction".
 
-<div style="color: #2f6473; background-color: #def2f8; border-color: #d1edf6;">
-<div class="proof">
 <p>The sum of any number of successive odd numbers, beginning from unity, is a square number, namely the square of half the even number which follows the last odd number.
 Let this proposition be true in any one single instance; that is, \(n\) being some whole number, let \(1,\, 3,\, 5,\, \ldots\) up to \(2n+1\) put together give \((n+1)^2\).
 Then the next odd number being \(2n+3\), the sum of all the odd numbers up to \(2n+3\) will be \((n+1)^2+2n+3\), or \(n^2+4n+4\), or \((n+2)^2\).  But \(n+2\) is half of the even number next following \(2n+3\): consequently, if the proposition be true of any one set of odd numbers, it is true of one more.  But it is true of the first odd number \(1\), for this is the square of half the even number next following.  Consequently, being true of \(1\), it is true of \(1+3\); being true of \(1+3\), it is true of \(1+3+5\); being true of \(1+3+5\), it is true of \(1+3+5+7\), and so on, {\em ad infinitum}.</p>
-</div>
-</div>
 
 This is the original version.
 
diff --git a/doc/en/Students/FAQ.md b/doc/en/Students/FAQ.md
index 1a2f228d9..a75fe1b63 100644
--- a/doc/en/Students/FAQ.md
+++ b/doc/en/Students/FAQ.md
@@ -8,7 +8,7 @@ You often need to enter an answer which is an algebraic expression. Details and
 
 ## Why is my answer "invalid"?
 
-STACK validates students' answers before they are graded, checking if the answers are in an acceptable syntax and giving the student a chance to confirm their answer is correct. By default, answers not explicitly specifying multiplication (fx. \(2x\) instead of \(2*x\)) are not accepted. This is linked to a core [philosophy of STACK](../About/The_philosophy_of_STACK.md); students should not be penalized for poor computer syntax. It is better to bug students until their answer is unambiguous, than to risk students being marking wrong for typic in "sinx" instead of "sin(x)" and having the computer interpret it as "s\*i\*n\*x".
+STACK validates students' answers before they are graded, checking if the answers are in an acceptable syntax and giving the student a chance to confirm their answer is correct. By default, answers not explicitly specifying multiplication (fx. \(2x\) instead of \(2*x\)) are not accepted. This is linked to a core [philosophy of STACK](../About/The_philosophy_of_STACK.md); students should not be penalized for poor computer syntax. It is better to bug students until their answer is unambiguous, than to risk students being marking wrong for typing in "sinx" instead of "sin(x)" and having the computer interpret it as "s\*i\*n\*x".
 
 That being said, there are options in STACK to be less strict with student syntax, so that the system may accept "2x" as a valid input. The question author has to activate this function, so contact your teacher if you think they should choose this option.
 
@@ -39,4 +39,4 @@ If the bug seems to concern something outside of the question, for example the q
 
 ## How do I make the fonts bigger?
 
-See the information on [Accessibility](Accessibility.md).
\ No newline at end of file
+See the information on [Accessibility](Accessibility.md). 
\ No newline at end of file
diff --git a/doc/en/Topics/Differential_equations.md b/doc/en/Topics/Differential_equations.md
index 4a1d42af7..ed78f9b6d 100644
--- a/doc/en/Topics/Differential_equations.md
+++ b/doc/en/Topics/Differential_equations.md
@@ -17,16 +17,16 @@ The syntax to enter a derivative in Maxima is `diff(y,x,n)`.  Teachers need to u
 Students' answers always have noun forms added. If a student types in `diff(y,x)` then this is protected by a special function `noundiff(y,x)` (etc), and ends up being sent to answer test as `'diff(y,x,1)`. If a student types in (literally) `diff(y,x)+1 = 0` this will end up being sent to answer test as `'diff(y,x,1)+1 = 0`.
 
 The answer test `AlgEquiv` evaluates all nouns.   This has a (perhaps) unexpected side-effect that `noundiff(y,x)` will be equivalent to `0`, and `noundiff(y(x),x)` is not.  For this reason we have an alternative [answer test](../Authoring/Answer_Tests/index.md) `AlgEquivNouns` which does not evaluate all the nouns.
-The `ATEqualComAss` also evaluates its arguments but does not "simplify" them.  So, counter-intuatively perhaps, we currently do have `ATEqualComAss(diff(x^2,x), 2*x);` as true.
+The `ATEqualComAss` also evaluates its arguments but does not "simplify" them.  So, counter-intuitively perhaps, we currently do have `ATEqualComAss(diff(x^2,x), 2*x);` as true.
 
-Students might expect to enter expressions like \( y' \), \( \dot{y} \) or \( y_x \) (especially if you are using `derivabbrev:true`, see below).   The use by Maxima of the apostrophe which affects evaluation also has a side-effect that we can't accept `y'` as valid student input.  Input `y_x` is an atom.  Individual questions could interpet this as `'diff(y,x)` but there is no systematic mechanism for intepreting subscripts as derivatives.  Input `dy/dx` is the division of one atom `dy` by another `dx` and so will commute with other multiplication and division in the expression as normal.  There is no way to protect input `dy/dx` as \( \frac{\mathrm{d}y}{\mathrm{d}x}\).  The only input which is interpreted by STACK as a derivative is Maxima's `diff` function, and students must type this as input.
+Students might expect to enter expressions like \( y' \), \( \dot{y} \) or \( y_x \) (especially if you are using `derivabbrev:true`, see below).   The use by Maxima of the apostrophe which affects evaluation also has a side-effect that we can't accept `y'` as valid student input.  Input `y_x` is an atom.  Individual questions could interpret this as `'diff(y,x)` but there is no systematic mechanism for interpreting subscripts as derivatives.  Input `dy/dx` is the division of one atom `dy` by another `dx` and so will commute with other multiplication and division in the expression as normal.  There is no way to protect input `dy/dx` as \( \frac{\mathrm{d}y}{\mathrm{d}x}\).  The only input which is interpreted by STACK as a derivative is Maxima's `diff` function, and students must type this as input.
 
-The exprssion `diff(y(x),x)` is not the same as `diff(y,x)`.  In Maxima `diff(y(x),x)` is not evaluated further.  Getting students to type `diff(y(x),x)` and not `diff(y,x)` will be a challange.  Hence, if you want to condone the difference, it is probably best to evaluate the student's answer in the feedback variables as follows to ensure all occurances of `y` become `y(x)`.
+The expression `diff(y(x),x)` is not the same as `diff(y,x)`.  In Maxima `diff(y(x),x)` is not evaluated further.  Getting students to type `diff(y(x),x)` and not `diff(y,x)` will be a challenge.  Hence, if you want to condone the difference, it is probably best to evaluate the student's answer in the feedback variables as follows to ensure all occurrences of `y` become `y(x)`.
 
     ans1:'diff(y(x),x)+1 = 0;
     ansyx:subst(y,y(x),ans1);
 
-Trying to substitute `y(x)` for `y` will throw an error.  Don't use the following, as if the student has used `y(x)` then it will become `y(x)(x)`! 
+Trying to substitute `y(x)` for `y` will throw an error.  Don't use the following, as if the student has used `y(x)` then it will become `y(x)(x)`!
 
     ans1:'diff(y,x)+1 = 0;
     ansyx:ev(ans1,y=y(x));
@@ -39,7 +39,7 @@ Maxima has two notations to display ODEs.
 
 If `derivabbrev:false` then`'diff(y,x)` is displayed in STACK as \( \frac{\mathrm{d}y}{\mathrm{d}x}\).   Note this differs from Maxima's normal notation of \( \frac{\mathrm{d}}{\mathrm{d}x}y\).
 
-If `derivabbrev:true` then `'diff(y,x)` is displayed in STACK and Maxima as \( y_x \).  
+If `derivabbrev:true` then `'diff(y,x)` is displayed in STACK and Maxima as \( y_x \).
 
 * Extra brackets are sometimes produced around the differential.
 * You must have `simp:true` otherwise the display routines will not work.
@@ -178,12 +178,12 @@ However, it is unusual to want to specify the name of a constant.  A student may
 Sometimes students use the \(\pm\) operator, e.g. instead of typing in \( Ae^{\lambda t} \) they type in \( \pm Ae^{\lambda_1 t} \) as `+-A*e^(lambda*t)`.  The \(\pm\) has a somewhat ambiguous status in mathematics, but it is likely that many people will want to condone its use here.
 
 Internally, the \(\pm\) operator is represented with an infix (or prefix) operation `#pm#`, which is part of STACK but not core Maxima.  Instead of `a+-b` teachers must type `a#pm#b`.  Students' answers get translated into this format.
-Mostly when dealing with expressions you need to remove the \(\pm\) operator.  To remove the \(\pm\) operator STACK provides the function `pm_replace(ex)` which performs the re-write rules 
+Mostly when dealing with expressions you need to remove the \(\pm\) operator.  To remove the \(\pm\) operator STACK provides the function `pm_replace(ex)` which performs the re-write rules
 \[ a\pm b \rightarrow (a+b) \vee (a-b) \]
 \[ \pm a \rightarrow a \vee -a \]
 (actually using STACK's `nounor` operator to prevent evaluation).
 
-If you simply want to implement the re-write rule \( a\pm b \rightarrow a+b, \) i.e. ignore the \(\pm\) operator, then you can use `subst( "+","#pm#", ex)`.  For example, this substitution can be done in the feebdack variables on a student's answer.  If you would like to test code offline with `#pm#` then you will need to make use of the [Maxima sandbox](../CAS/STACK-Maxima_sandbox.md).
+If you simply want to implement the re-write rule \( a\pm b \rightarrow a+b, \) i.e. ignore the \(\pm\) operator, then you can use `subst( "+","#pm#", ex)`.  For example, this substitution can be done in the feedback variables on a student's answer.  If you would like to test code offline with `#pm#` then you will need to make use of the [Maxima sandbox](../CAS/STACK-Maxima_sandbox.md).
 
 ## Second order linear differential equations with constant coefficients ##
 
@@ -366,4 +366,4 @@ Further examples are
 
 ## See also
 
-[Maxima reference topics](index.md#reference)
\ No newline at end of file
+[Maxima reference topics](index.md#reference) 
\ No newline at end of file
diff --git a/doc/en/Topics/GeoGebra.md b/doc/en/Topics/GeoGebra.md
index 6d6f38c64..9ba1d6b95 100644
--- a/doc/en/Topics/GeoGebra.md
+++ b/doc/en/Topics/GeoGebra.md
@@ -26,7 +26,7 @@ Move the points \(A\) and \(B\) (on a GeoGebra applet) so that the line \(AB\) i
 
 Notes.
 
-* \(m\) and \(c\) are defined by STACK in the question variables.  Ultimately these could be randomly genereated.  They illustrate how to _set_ values in an applet.
+* \(m\) and \(c\) are defined by STACK in the question variables.  Ultimately these could be randomly generated.  They illustrate how to _set_ values in an applet.
 * We should listen to the _gradient_ of the line \(AB\) as an input.  This illustrates how to _watch_ a value in GeoGebra and link it to a STACK input.
 * \(A\) and \(B\) are points in the GeoGebra applet.  We need to _remember_ the position a student leaves the points in.
 * In this question, the potential response tree should multiply the variable \(m\) by the gradient of \(AB\) to check this is \(-1\).  We don't worry about the position of the student's line otherwise.
@@ -35,7 +35,7 @@ Notes.
 
 The first step is to create a GeoGebra applet and publish it online.   You will need the material id from the URL in GeoGebra to link the worksheet to a STACK question.
 
-1. Login to [https://www.geogebra.org/](https://www.geogebra.org/) 
+1. Login to [https://www.geogebra.org/](https://www.geogebra.org/)
 2. Create a blank applet directly on the GeoGebra website.
  * Create numbers `m=2` and `c=3`.  These will be given a value by STACK when the question is started by the student, but we must set sensible initial values.
  * Create the line `l=m*x+c`.
@@ -63,7 +63,7 @@ Set the question text - before entering make sure that the editor is switched to
 
 Notice this uses the `[[geogebra]]` question block. Then complete the question as follows.
 
-1. Make sure the question text is "HTML" format (not moodle auto format, or something else).
+1. Make sure the question text is "HTML" format (not Moodle auto format, or something else).
 2. Input `ans1` should have Model answer equal to `-1/m`.
 3. Input `ans1` should "Forbid float" set to no/false (GeoGebra will return floating point numbers)
 4. Set up the PRT with node 1 testing `ATNumAbsolute(ans1*m, -1, 0.1)`.  This checks the product of the gradient of the lines is within \(0.1\) of \(-1\) - i.e. are they close to perpendicular.  (You could opt for a strict algebraic equivalence `ATAlgEquiv(ans1*m, -1)` if you prefer.)
diff --git a/doc/en/Topics/Levenshtein_distance.md b/doc/en/Topics/Levenshtein_distance.md
index a1303244b..ecebe68f8 100644
--- a/doc/en/Topics/Levenshtein_distance.md
+++ b/doc/en/Topics/Levenshtein_distance.md
@@ -9,7 +9,7 @@ The use of this distance automatically includes an element of spell checking, wh
 
 In STACK `levenshtein(s, t)` takes strings `s`, `t` to compare and returns an integer, the Levensthein distance between `s` and `t`.  This is basically the number of single-character edits.  For example `levenshtein("Add", "And")` gives 1, since one letter needs to be changed. `levenshtein("Add", "and")` gives 2, since two leters need to be changed.  Adding or removing letters are each a single edit, so that `levenshtein("Subtract", "Subtraction");` gives 3.
 
-Rather than using this "distance" a tolerance is defined by the normalised "Levenshtein similarity" between 0 (totally different) and 1 (identical).  The Maxima code for this function is simple enough to list here explicitly. 
+Rather than using this "distance" a tolerance is defined by the normalised "Levenshtein similarity" between 0 (totally different) and 1 (identical).  The Maxima code for this function is simple enough to list here explicitly.
 
      levenshtein_plv(s, t) := 1.0-levenshtein(s, t)/max(slength(s), slength(t));
 
@@ -33,24 +33,24 @@ Notes on using the answer test in STACK.
 1. The first argument to the test (the "student's answer") must be a string.
 2. The second argument to the test (the "teacher's answer") must be a list in the form `[allow, deny]` where both `allow` and `deny` are themselves lists of strings.  The `allow` list must be non-empty, but the `deny` list could be empty.
 3. The option must be used.  Either give the numerical tolerance as a number, or a list of options.  The numerical tolerance must be the first element of the options list.
-4. By default the test is case-insensitive.  If you include the atom `CASE` in the list of options then the matching is case sensitive, potentially increasing the Levenshtein distance between strings.  E.g. use answer test option `[0.9, CASE]` for a case-senstive test with a tolerance of 0.9.
-5. By default this test consolidates whitespace, e.g. replaces tab and newline characters with a single space, trims whitespace from each end and separates with at most one space character.  If you include the atom `WHITESPACE` in the list of options then whitesapace is not consolidated.
+4. By default the test is case-insensitive.  If you include the atom `CASE` in the list of options then the matching is case sensitive, potentially increasing the Levenshtein distance between strings.  E.g. use answer test option `[0.9, CASE]` for a case-sensitive test with a tolerance of 0.9.
+5. By default this test consolidates whitespace, e.g. replaces tab and newline characters with a single space, trims whitespace from each end and separates with at most one space character.  If you include the atom `WHITESPACE` in the list of options then whitespace is not consolidated.
 
 The current answer test provides feedback indicating which of the allow strings was most similar.  The test does not provide feedback indicating which of the deny strings was most similar, but if you can find a use-case which needs deny based feedback please contact the developers and we will add an option.
 
-The answernote records the most similar allow string, the most similar deny string and the corresoding tolerance values.  It is likley that a teacher will need to examine students' answers in the fist use cycle and fine tune the `allow`, `deny` and tolerance values (perhaps with a regrade) to reach an acceptable level of test reliability: the use of the tolerance means this test is not as objective as some other STACK assessments.
+The answernote records the most similar allow string, the most similar deny string and the corresponding tolerance values.  It is likely that a teacher will need to examine students' answers in the fist use cycle and fine tune the `allow`, `deny` and tolerance values (perhaps with a regrade) to reach an acceptable level of test reliability: the use of the tolerance means this test is not as objective as some other STACK assessments.
 
 It is likely this test will benefit from a wide range of text pre-processing options prior to the test being executed, e.g. using functions from Maxima's stringproc library.  For example
 
 * remove (ignore) accents and diacritical marks
 
-At this point we do not propose to add these as options to the test itself as the pre-processing can be done in the feedback variables as required.  However, pre-processing does affect the feedback given by the test and so test options might be very useful.  If you create such processing functions and have compelling use-cases we would appreciate an opportinity to document, and support them as core functionality: please contact the developers.
+At this point we do not propose to add these as options to the test itself as the pre-processing can be done in the feedback variables as required.  However, pre-processing does affect the feedback given by the test and so test options might be very useful.  If you create such processing functions and have compelling use-cases we would appreciate an opportunity to document, and support them as core functionality: please contact the developers.
 
 ## Advice on processing strings in this context.
 
 1. To trim whitespace and full stops from each end of a string, you can define `sans1:strim(" .",ans1);` in the feedback variables.
-2. STACK provides a function `sremove_chars(rem, st)` which removes all occurances of each _character_ in the string `rem` from the string `st`.  For example to remove all selected punctuation characters use `sremove_chars(".,!?", ans1)`.
-3. STACK provides a function `ssquish` which changes tabs and newlines to spaces; trips whitespace at the ends; and replaces multiple whitespaces with a single whitespace.
+2. STACK provides a function `sremove_chars(rem, st)` which removes all occurrences of each _character_ in the string `rem` from the string `st`.  For example to remove all selected punctuation characters use `sremove_chars(".,!?", ans1)`.
+3. STACK provides a function `ssquish` which changes tabs and newlines to spaces; trips whitespace at the ends; and replaces multiple whitespace characters with a single whitespace.
 
 ## Writing a STACK question
 
@@ -76,7 +76,7 @@ Then:
 
 With this set of allow strings we have `ans1:"complete square"` gives the following answer note from the potential response tree
 
-    ATLevenshtein_far: [[0.78947,"Complete the square"],[0.4,"Square"]]. 
+    ATLevenshtein_far: [[0.78947,"Complete the square"],[0.4,"Square"]].
 
 The note `ATLevenshtein_far` means the closest string was in the allow list, but it was too far away.  The rest of the note means that the closest string found in `allow1` was "Complete the square" with similarity 0.78947. The closest string found in `deny1` was "Square" with similarity 0.4.  If you want to accept "complete square" as a correct answer you have two choices: (i) add it to `allow1`, or (ii) reduce the required similarity below 0.789.
 
diff --git a/doc/en/Topics/Parsons.md b/doc/en/Topics/Parsons.md
index e7d586729..01a5d02e8 100644
--- a/doc/en/Topics/Parsons.md
+++ b/doc/en/Topics/Parsons.md
@@ -22,7 +22,7 @@ We might expect/require two conscious and separate blocks
 2.  Assume \(B\), \(\cdots\), hence \(A\).
 
 The order in which these two sub-proofs are presented is (normally) irrelevant.  That is the _if and only if_ proof construct allows its two sub-proofs to commute.  This is precisely the same sense in which \(A=B\) and \(B=A\) are equivalent. There are _blocks_ within the proof which can change order. Furthermore, since proofs are often nested blocks these sub-proofs may themselves have acceptable options for correctness.
-Proofs often contain local variables.  Use of explicit block-structres clarify the local scope of variables, and the local scope of assumptions.
+Proofs often contain local variables.  Use of explicit block-structures clarify the local scope of variables, and the local scope of assumptions.
 
 STACK provides ["proof construction functions"](../Proof/Proof_CAS_library.md) with arguments. For example, an if and only if proof would be represented as `proof_iff(A,B)`.  Here `A` and `B` are either sub-proofs or strings to be shown to the student.
 
@@ -75,7 +75,7 @@ The example question text below contains a Parson's block. Within the header of
 
 Notes:
 
-1. The Parson's block requires a JSON object containins `"key":"string"` pairs. The `string` will be shown to the student.  The student's answer will be returned in terms of the `key` tags.  Numbers can be used as keys, but named keys above will be more specific.  We strongly recommend using named keys.
+1. The Parson's block requires a JSON object containing `"key":"string"` pairs. The `string` will be shown to the student.  The student's answer will be returned in terms of the `key` tags.  Numbers can be used as keys, but named keys above will be more specific.  We strongly recommend using named keys.
 2. The `\` character in the string must be protected!  Notice that `\(...\)` needs to be typed as `\\(...\\)`.
 3. The [Parson's block](../Authoring/Parsons.md) has a wide range of options such as `height` and `width` which are documented elsewhere.
 
@@ -98,7 +98,7 @@ The student's answer will be a _JSON string_, but we need to interpret which of
 
 Then you can set up the potential response tree to be `ATAlgEquiv(sa,ta)` to confirm the student's answer is the same as the teacher's answer.
 
-# Example question 2: a proof with interchangable block order
+# Example question 2: a proof with interchangeable block order
 
 The following Parson's question is an _if and only if_ proof, containing two blocks in order.
 
@@ -147,7 +147,7 @@ The two blocks can be in either order.  Prooflib provides a function to automati
 
 There is one change in input from the above example:
 
-1. The _Model answer_ field should construct a JSON object from the teacher's answer `ta` using `proof_parsons_key_json(ta, proof_steps)`.  
+1. The _Model answer_ field should construct a JSON object from the teacher's answer `ta` using `proof_parsons_key_json(ta, proof_steps)`.
 
 In this example all steps are used, however if you add extra steps (distracters) then the model answer field has to separate these into used and unused lists, hence both the teacher's answer `ta` and the whole `proof_steps` list is needed.
 
diff --git a/doc/en/Topics/Propositional_Logic.md b/doc/en/Topics/Propositional_Logic.md
index a26411a23..360ba49d6 100644
--- a/doc/en/Topics/Propositional_Logic.md
+++ b/doc/en/Topics/Propositional_Logic.md
@@ -4,7 +4,7 @@ STACK loads the "logic" package from Maxima.
 
 ## Boolean functions
 
-Maxima has Boolean operators `and`, `or`, and `not`.  These rely on the underlying LISP implementation and as a result the `simp:false` is ignored.  
+Maxima has Boolean operators `and`, `or`, and `not`.  These rely on the underlying LISP implementation and as a result the `simp:false` is ignored.
 To illustrate the problem, try the following.
 
     simp:false$
@@ -21,15 +21,15 @@ which would be a natural way to express the solution to a quadratic equation.
 
 To solve this problem STACK has introduced `nounand` and `nounor` which are commutative and associative operators.
 
-Students do *not* need to use `nounand` and `nounor` in answers.  
+Students do *not* need to use `nounand` and `nounor` in answers.
 Any `and` and `or` operators occurring in their answers are always automatically converted into these noun forms.
 
-Teachers *always* need to use `nounand` and `nounor` in CAS expressions when they want to write non-simplifying expressions.  
-For example, when defining the "teacher's answer" they should use the noun forms as appropriate.  
+Teachers *always* need to use `nounand` and `nounor` in CAS expressions when they want to write non-simplifying expressions.
+For example, when defining the "teacher's answer" they should use the noun forms as appropriate.
 Teachers often need to use Boolean logic, and so need to consciously separate the difference between these operators and concepts.
 
-Note, the answer tests do *not* convert noun forms to the Maxima forms.  
-Otherwise both `x=1 or x=2` and `x=1 or x=3` would be evaluated to `false` and a teacher could not tell that they are different!  
+Note, the answer tests do *not* convert noun forms to the Maxima forms.
+Otherwise both `x=1 or x=2` and `x=1 or x=3` would be evaluated to `false` and a teacher could not tell that they are different!
 To replace all `nounand` (etc) operators and replace them with the Maxima equivalent, use `noun_logic_remove(ex)`.
 
 ## Operators and notes
@@ -53,7 +53,7 @@ The function `verb_logic(ex)` will remove the noun forms such as `nounand` and s
 
 ## Answer tests
 
-The answer tests protect the logical operators.  This behaviour is to prevent evaluation of expressions such as `x=1` as a boolean predicate fuction.  I.e. the default behaviour is to give priority to the assumption an arbitary expression is an algebraic expression, or a set of equations, inequalities etc.
+The answer tests protect the logical operators.  This behaviour is to prevent evaluation of expressions such as `x=1` as a boolean predicate function.  I.e. the default behaviour is to give priority to the assumption an arbitrary expression is an algebraic expression, or a set of equations, inequalities etc.
 
 The answer test `PropLogic` replaces all noun logical expressions with the Maxima versions, and then tests two expressions using the function `logic_equiv` from Maxima's logic package.  This answer test does not support sets, lists, etc.
 
diff --git a/doc/en/Topics/Unsorted_multi_input.md b/doc/en/Topics/Unsorted_multi_input.md
index 834b65a90..59c98a624 100644
--- a/doc/en/Topics/Unsorted_multi_input.md
+++ b/doc/en/Topics/Unsorted_multi_input.md
@@ -43,15 +43,15 @@ Continuing the above example, in the PRT use
 
 ### Dealing with duplicate entries ###
 
-How do we decide partial credit when there may be duplicates, e.g. eignevalues with repetion?  If the teacher's answer is `[1,1,2]` then we can't use the above example based on sets.
+How do we decide partial credit when there may be duplicates, e.g. eigenvalues with repetition?  If the teacher's answer is `[1,1,2]` then we can't use the above example based on sets.
 
-STACK provides a maxima function `list_cancel(l1,l2)` which removes any common elements from `[l1,l2]`, with duplication.  E.g. use the following in the quesion variables.
+STACK provides a maxima function `list_cancel(l1,l2)` which removes any common elements from `[l1,l2]`, with duplication.  E.g. use the following in the question variables.
 
     sans:{ans1, ans2};
     [missing, notwanted]:list_cancel([sans, tas]);
     score:max(1-(length(missing)+length(notwanted))/(2*length(tas)),0);
 
-Note that `list_cancel` will not establish algebraic equialence and within this function two expressions are considered the same using maxima's `is(ex1=ex2))`.  Hence, some pre-processing of the lists might be needed, depending on the situation and what you consider is the "same".  For example if we have
+Note that `list_cancel` will not establish algebraic equivalence and within this function two expressions are considered the same using maxima's `is(ex1=ex2))`.  Hence, some pre-processing of the lists might be needed, depending on the situation and what you consider is the "same".  For example if we have
 
     l1:[x^2,x^3,x^2-1,x+x];
     l2:[x^2,x^4,(x-1)*(x+1),2*x];
diff --git a/doc/en/Topics/index.md b/doc/en/Topics/index.md
index 08156dae7..b8f2f71b0 100644
--- a/doc/en/Topics/index.md
+++ b/doc/en/Topics/index.md
@@ -1,6 +1,6 @@
 # Mathematical topics
 
-This section of the STACK documentation contains information on how to author questions in particular mathematics topics.  Many topics have differente requirements, e.g. physics needs support for scientific units.  These pages contain know-how on linking together features such as [inputs](../Authoring/Inputs.md), [answer tests](../Authoring/Answer_Tests/index.md) and [options](../Authoring/Options.md) to write questions in particular subject areas.
+This section of the STACK documentation contains information on how to author questions in particular mathematics topics.  Many topics have different requirements, e.g. physics needs support for scientific units.  These pages contain know-how on linking together features such as [inputs](../Authoring/Inputs.md), [answer tests](../Authoring/Answer_Tests/index.md) and [options](../Authoring/Options.md) to write questions in particular subject areas.
 
 Current topics include:
 
@@ -14,4 +14,4 @@ Current topics include:
 * [Propositional Logic](Propositional_Logic.md)
 * [Scientific Units](Units.md)
 * [Vector Calculus](Vector_Calculus.md)
-* [Unsorted multi-input](Unsorted_multi_input.md) questions
\ No newline at end of file
+* [Unsorted multi-input](Unsorted_multi_input.md) questions 
\ No newline at end of file
-- 
GitLab