@pretextbook/pretext-html 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +31 -2
  2. package/assets/preview-html.xsl +16 -0
  3. package/assets/upstream.json +1 -1
  4. package/assets/xsl/README.md +25 -24
  5. package/assets/xsl/entities.ent +11 -0
  6. package/assets/xsl/extract-dynamic.xsl +54 -3
  7. package/assets/xsl/extract-gdscript.xsl +61 -0
  8. package/assets/xsl/extract-sageplot.xsl +3 -0
  9. package/assets/xsl/localizations/README.md +24 -24
  10. package/assets/xsl/localizations/it-IT.xml +37 -41
  11. package/assets/xsl/pretext-assembly.xsl +190 -30
  12. package/assets/xsl/pretext-beamer.xsl +57 -12
  13. package/assets/xsl/pretext-common.xsl +175 -30
  14. package/assets/xsl/pretext-epub.xsl +4 -6
  15. package/assets/xsl/pretext-fo.xsl +127 -67
  16. package/assets/xsl/pretext-html.xsl +350 -94
  17. package/assets/xsl/pretext-jupyter.xsl +1 -0
  18. package/assets/xsl/pretext-latex-classic.xsl +2 -2
  19. package/assets/xsl/pretext-latex-common.xsl +296 -151
  20. package/assets/xsl/pretext-latex.xsl +16 -6
  21. package/assets/xsl/pretext-numbers.xsl +10 -0
  22. package/assets/xsl/pretext-revealjs.xsl +69 -4
  23. package/assets/xsl/pretext-runestone-fitb.xsl +179 -84
  24. package/assets/xsl/pretext-runestone-static.xsl +72 -20
  25. package/assets/xsl/pretext-runestone.xsl +32 -25
  26. package/assets/xsl/pretext-text-utilities.xsl +7 -0
  27. package/assets/xsl/pretext-text.xsl +17 -0
  28. package/assets/xsl/publisher-variables.xsl +109 -111
  29. package/assets/xsl/support/play-button/README.md +1 -3
  30. package/assets/xsl/tests/README.md +1 -1
  31. package/assets/xsl/utilities/README.md +6 -8
  32. package/assets/xsl-bundle.json +1 -1
  33. package/dist/cli-BUrNZxov.js +1098 -0
  34. package/dist/cli.js +1 -1
  35. package/dist/html-static.d.ts +20 -0
  36. package/dist/index.browser.js +598 -374
  37. package/dist/index.d.ts +4 -0
  38. package/dist/index.js +35 -30
  39. package/dist/renderer.d.ts +40 -1
  40. package/dist/skeleton.d.ts +41 -0
  41. package/dist/xrefs.d.ts +54 -0
  42. package/package.json +2 -1
  43. package/dist/cli-D0m0Ha1j.js +0 -856
@@ -102,7 +102,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
102
102
  </xsl:when>
103
103
  <xsl:otherwise>
104
104
  <!-- Report if a seed is not provided-->
105
- <xsl:message>PTX:FALLBACK: Dynamic exercise "<xsl:value-of select="@visible-id"/>" is missing setup @seed for static content generation.</xsl:message>
105
+ <xsl:message>PTX:FALLBACK: Dynamic exercise "<xsl:apply-templates select="." mode="unique-id" />" is missing setup @seed for static content generation.</xsl:message>
106
106
  <xsl:text>1234</xsl:text>
107
107
  </xsl:otherwise>
108
108
  </xsl:choose>
@@ -139,12 +139,20 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
139
139
  <xsl:text>,&#xa;"dyn_imports": [</xsl:text>
140
140
  <xsl:text>"BTM"</xsl:text>
141
141
  <!-- Future: add additional packages here -->
142
+ <xsl:if test="setup/jsimports">
143
+ <xsl:apply-templates select="setup/jsimports/jslibrary" mode="js-import"/>
144
+ </xsl:if>
142
145
  <xsl:text>]</xsl:text>
143
146
  </xsl:if>
144
147
  <!-- Names assigned to the blanks. -->
145
148
  <!-- Empty if none named. -->
146
149
  <xsl:text>,&#xa;"blankNames": {</xsl:text>
147
- <xsl:apply-templates select="statement//fillin" mode="declare-blanks" />
150
+ <xsl:for-each select="statement//fillin">
151
+ <xsl:if test="position() > 1">
152
+ <xsl:text>, </xsl:text>
153
+ </xsl:if>
154
+ <xsl:apply-templates select="." mode="declare-blank"/>
155
+ </xsl:for-each>
148
156
  <xsl:text>}</xsl:text>
149
157
  <xsl:if test="$b-is-dynamic">
150
158
  <!-- The actual setup code is javascript enclosed in quotes. -->
@@ -163,10 +171,21 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
163
171
  <xsl:variable name="multiAns">
164
172
  <xsl:apply-templates select="evaluation" mode="get-multianswer-check"/>
165
173
  </xsl:variable>
174
+ <!-- Verify match between fillin and evaluate -->
175
+ <xsl:if test="count(evaluation/evaluate[not(@all='yes')]) != count(statement//fillin)">
176
+ <xsl:message>PTX:ERROR: "<xsl:apply-templates select="." mode="unique-id"/>" has <xsl:value-of
177
+ select="count(statement//fillin)"/> blanks but <xsl:value-of
178
+ select="count(evaluation/evaluate[not(@all='yes')])"/> "evaluate" elements; they must correspond one-to-one.</xsl:message>
179
+ </xsl:if>
166
180
  <!-- Generate test/feedback pair for each fillin -->
167
- <xsl:apply-templates select="statement//fillin" mode="dynamic-feedback">
168
- <xsl:with-param name="multiAns" select="$multiAns" />
169
- </xsl:apply-templates>
181
+ <xsl:for-each select="statement//fillin">
182
+ <xsl:if test="position() > 1">
183
+ <xsl:text>, </xsl:text>
184
+ </xsl:if>
185
+ <xsl:apply-templates select="." mode="dynamic-feedback">
186
+ <xsl:with-param name="multiAns" select="$multiAns" />
187
+ </xsl:apply-templates>
188
+ </xsl:for-each>
170
189
  <xsl:text>]</xsl:text>
171
190
  <xsl:text>&#xa;}</xsl:text>
172
191
  </script>
@@ -176,6 +195,16 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
176
195
  </div>
177
196
  </xsl:template>
178
197
 
198
+ <!-- Find the sequential position of the fillin relative to its ancestor statement -->
199
+ <xsl:template match="fillin" mode="blank-number">
200
+ <xsl:variable name="the-fillin" select="."/>
201
+ <xsl:for-each select="ancestor::statement[1]//fillin">
202
+ <xsl:if test="generate-id() = generate-id($the-fillin)">
203
+ <xsl:value-of select="position()"/>
204
+ </xsl:if>
205
+ </xsl:for-each>
206
+ </xsl:template>
207
+
179
208
  <!-- Fillins can be provided a name or use a default rule -->
180
209
  <xsl:template match="fillin" mode="blank-name">
181
210
  <xsl:choose>
@@ -184,26 +213,58 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
184
213
  </xsl:when>
185
214
  <xsl:otherwise>
186
215
  <xsl:text>blank</xsl:text>
187
- <xsl:value-of select="position()" />
216
+ <xsl:apply-templates select="." mode="blank-number" />
188
217
  </xsl:otherwise>
189
218
  </xsl:choose>
190
219
  </xsl:template>
191
220
 
192
221
  <!-- Creating a list of blank names. -->
193
- <xsl:template match="fillin" mode="declare-blanks">
222
+ <xsl:template match="fillin" mode="declare-blank">
223
+ <xsl:if test="not(@mode)">
224
+ <xsl:message>PTX:FALLBACK: a "fillin" of interactive exercise "<xsl:apply-templates
225
+ select="ancestor::statement[1]/parent::*" mode="unique-id"/>" has no @mode, so "string" will be used. A response is then compared as plain text, and an @ansobj answer is rendered with its "toString" and not as mathematics. Set @mode to "math", "number", or "string" to say which is wanted.</xsl:message>
226
+ </xsl:if>
194
227
  <xsl:variable name="blankNum">
195
- <xsl:value-of select="position()" />
228
+ <xsl:apply-templates select="." mode="blank-number" />
196
229
  </xsl:variable>
197
- <xsl:if test="$blankNum>1">
198
- <xsl:text>, </xsl:text>
199
- </xsl:if>
200
230
  <xsl:call-template name="quote-string">
201
231
  <xsl:with-param name="text">
202
232
  <xsl:apply-templates select="." mode="blank-name"/>
203
233
  </xsl:with-param>
204
234
  </xsl:call-template>
205
235
  <xsl:text>: </xsl:text>
206
- <xsl:value-of select="$blankNum - 1"/>
236
+ <xsl:value-of select="number($blankNum) - 1"/>
237
+ </xsl:template>
238
+
239
+ <!-- Identify external javascript libraries, either as asset or by url -->
240
+ <xsl:template match="jslibrary" mode="js-import-path">
241
+ <xsl:choose>
242
+ <xsl:when test="@source">
243
+ <xsl:value-of select="$external-directory"/>
244
+ <xsl:value-of select="@source"/>
245
+ </xsl:when>
246
+ <xsl:when test="@url">
247
+ <xsl:value-of select="@url"/>
248
+ </xsl:when>
249
+ <xsl:otherwise>
250
+ <xsl:message>PTX:WARNING: a "jslibrary" element needs either a @source (project-local) or a @url (remote) attribute, and this one has neither, so it will be ignored.</xsl:message>
251
+ </xsl:otherwise>
252
+ </xsl:choose>
253
+ </xsl:template>
254
+
255
+ <!-- A "jslibrary" as an entry of the HTML "dyn_imports" array. The -->
256
+ <!-- array always leads with "BTM", so every entry here is preceded -->
257
+ <!-- by a comma. -->
258
+ <xsl:template match="jslibrary" mode="js-import">
259
+ <xsl:variable name="import-path">
260
+ <xsl:apply-templates select="." mode="js-import-path"/>
261
+ </xsl:variable>
262
+ <xsl:if test="string-length($import-path) > 0">
263
+ <xsl:text>, </xsl:text>
264
+ <xsl:call-template name="escape-quote-string">
265
+ <xsl:with-param name="text" select="$import-path"/>
266
+ </xsl:call-template>
267
+ </xsl:if>
207
268
  </xsl:template>
208
269
 
209
270
  <!-- #eval in a dynamic exercise (has setup) is to evaluate -->
@@ -215,7 +276,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
215
276
  <xsl:template match="eval[@obj]">
216
277
  <xsl:text>[%= </xsl:text>
217
278
  <xsl:choose>
218
- <xsl:when test="ancestor::m|ancestor::mrow">
279
+ <xsl:when test="ancestor::m|ancestor::md|ancestor::mrow">
219
280
  <xsl:text>toTeX(</xsl:text>
220
281
  <xsl:value-of select="@obj"/>
221
282
  <xsl:text>)</xsl:text>
@@ -227,7 +288,6 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
227
288
  <xsl:text> %]</xsl:text>
228
289
  </xsl:template>
229
290
 
230
-
231
291
  <!-- Part of static output content extraction process, -->
232
292
  <!-- this creates elements that will be pulled from the -->
233
293
  <!-- stand-alone page into a generated XML document that -->
@@ -305,6 +365,16 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
305
365
  <xsl:apply-templates select="de-environment" mode="runestone-setup"/>
306
366
  <xsl:text>});&#xa;</xsl:text>
307
367
  <xsl:text>var RNG = v._mobjs.menv.rng;&#xa;</xsl:text>
368
+ <!-- Option to define v._config for any data purposes -->
369
+ <xsl:if test="setup/config-json">
370
+ <xsl:text>const _config = v._config = JSON.parse("</xsl:text>
371
+ <xsl:call-template name="escape-json-string">
372
+ <xsl:with-param name="text">
373
+ <xsl:value-of select="setup/config-json"/>
374
+ </xsl:with-param>
375
+ </xsl:call-template>
376
+ <xsl:text>");&#xa;</xsl:text>
377
+ </xsl:if>
308
378
  <!-- Generate all of the XML-declared math objects -->
309
379
  <xsl:apply-templates select="setup/de-object" mode="runestone-setup"/>
310
380
  </xsl:template>
@@ -342,30 +412,23 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
342
412
  <!-- validating and parsing what the user enters as a response. -->
343
413
  <xsl:template name="setup-fillin-parsers">
344
414
  <xsl:text>v.types = [</xsl:text>
345
- <xsl:apply-templates select="statement//fillin" mode="setup-parsers" />
346
- <xsl:text>];&#xa;</xsl:text>
347
- </xsl:template>
348
-
349
- <!-- Create a call-back for what occurs post-rendering. -->
350
- <!-- This includes automated tasks as well as any script -->
351
- <!-- commands in setup/postRenderScript -->
352
- <xsl:template name="setup-postContent">
353
- <xsl:text>v.afterContentRender = function() {&#xa;</xsl:text>
354
- <xsl:if test="setup/postRenderScript">
355
- <xsl:value-of select="setup/postRenderScript"/>
415
+ <xsl:for-each select="statement//fillin">
416
+ <xsl:if test="position() > 1">
417
+ <xsl:text>, </xsl:text>
356
418
  </xsl:if>
357
- <xsl:text>};&#xa;</xsl:text>
419
+ <xsl:apply-templates select="." mode="setup-parsers"/>
420
+ </xsl:for-each>
421
+ <xsl:text>];&#xa;</xsl:text>
358
422
  </xsl:template>
359
423
 
360
-
361
424
  <!-- Each fillin defines a blank. Establish the list of parsers. -->
362
425
  <!-- During setup and called while creating dyn_vars. -->
363
426
  <xsl:template match="fillin" mode="setup-parsers">
364
- <xsl:if test="position() > 1">
365
- <xsl:text>, </xsl:text>
366
- </xsl:if>
367
427
  <xsl:choose>
368
- <xsl:when test="@mode='math-formula'">
428
+ <xsl:when test="@parser">
429
+ <xsl:value-of select="@parser"/>
430
+ </xsl:when>
431
+ <xsl:when test="@mode='math'">
369
432
  <xsl:text>v._mobjs.getParser()</xsl:text>
370
433
  </xsl:when>
371
434
  <xsl:when test="@mode='number'">
@@ -377,6 +440,17 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
377
440
  </xsl:choose>
378
441
  </xsl:template>
379
442
 
443
+ <!-- Create a call-back for what occurs post-rendering. -->
444
+ <!-- This includes automated tasks as well as any script -->
445
+ <!-- commands in setup/postRenderScript -->
446
+ <xsl:template name="setup-postContent">
447
+ <xsl:text>v.afterContentRender = function() {&#xa;</xsl:text>
448
+ <xsl:if test="setup/postRenderScript">
449
+ <xsl:value-of select="setup/postRenderScript"/>
450
+ </xsl:if>
451
+ <xsl:text>};&#xa;</xsl:text>
452
+ </xsl:template>
453
+
380
454
 
381
455
  <!-- ========================================================== -->
382
456
  <!-- Evaluation and Feedback -->
@@ -412,20 +486,12 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
412
486
  </xsl:if>
413
487
  </xsl:template>
414
488
 
415
- <!-- Return the index of an evaluate -->
416
- <xsl:template match="evaluation/evaluate" mode="get-index">
417
- <xsl:value-of select="position()"/>
418
- </xsl:template>
419
-
420
489
  <!-- Build feedback based on the #evaluate element. -->
421
490
  <xsl:template match="evaluate" mode="dynamic-feedback">
422
491
  <xsl:param name="multiAns"/>
423
492
  <xsl:param name="match-fillin"/>
424
493
 
425
- <!-- Defend against name mismatches -->
426
- <xsl:if test="@name and $match-fillin/@name and not(@name = $match-fillin/@name)">
427
- <xsl:message>PTX:ERROR: Dynamic content missing label "<xsl:value-of select="@visible-id"/>"</xsl:message>
428
- </xsl:if>
494
+ <!-- Catching name mismatch is detected by the caller. See "fillin"/"dynamic-feedback". -->
429
495
 
430
496
  <!-- First check is for correctness. -->
431
497
  <xsl:text>[</xsl:text>
@@ -474,12 +540,12 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
474
540
  <xsl:text>);&#xa;}</xsl:text>
475
541
  </xsl:when>
476
542
  <xsl:otherwise>
477
- <xsl:message>PTX:ERROR: fillin has an @ansobj with invalid or missing mode (valid: number|string|math) in "<xsl:value-of select="@visible-id"/>".</xsl:message>
543
+ <xsl:message>PTX:ERROR: fillin has an @ansobj with invalid or missing mode (valid: number|string|math) in "<xsl:apply-templates select="." mode="unique-id" />".</xsl:message>
478
544
  </xsl:otherwise>
479
545
  </xsl:choose>
480
546
  </xsl:when>
481
547
  <xsl:otherwise>
482
- <xsl:message>PTX:ERROR: No method provided to identify a correct answer for #fillin in "<xsl:value-of select="@visible-id"/>".</xsl:message>
548
+ <xsl:message>PTX:ERROR: No method provided to identify a correct answer for #fillin in "<xsl:apply-templates select="." mode="unique-id" />".</xsl:message>
483
549
  </xsl:otherwise>
484
550
  </xsl:choose>
485
551
  <xsl:text>, "feedback": "</xsl:text>
@@ -508,51 +574,73 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
508
574
  <!-- Template for answer checking. Actual work done by specialized templates. -->
509
575
  <xsl:template match="fillin" mode="dynamic-feedback">
510
576
  <xsl:param name="multiAns"/>
511
- <xsl:variable name="curFillIn" select="."/>
577
+
512
578
  <xsl:variable name="fillinName">
513
579
  <xsl:apply-templates select="." mode="blank-name"/>
514
580
  </xsl:variable>
515
581
  <xsl:variable name="blankNum">
516
- <xsl:value-of select="position()" />
582
+ <xsl:apply-templates select="." mode="blank-number"/>
517
583
  </xsl:variable>
518
584
 
519
- <!-- we need to know which #evaluate matches the #fillin -->
520
- <xsl:variable name="evaluate-index">
521
- <xsl:choose>
522
- <xsl:when test="ancestor::statement/../evaluation/evaluate[@name = $fillinName]">
523
- <xsl:apply-templates select="ancestor::statement/../evaluation/evaluate[@name = $fillinName]" mode="get-index"/>
524
- </xsl:when>
525
- <xsl:when test="ancestor::statement/../evaluation/evaluate[position() = $blankNum]">
526
- <xsl:value-of select="$blankNum"/>
527
- </xsl:when>
528
- <!-- No check matches: Make blank default. -->
529
- <xsl:otherwise>
530
- <xsl:number value="-1"/>
531
- </xsl:otherwise>
532
- </xsl:choose>
533
- </xsl:variable>
585
+ <!-- The multi-answer checker applies to the exercise as a whole, so -->
586
+ <!-- it is excluded from the numbering. Every other "evaluate" holds -->
587
+ <!-- a slot, named or not: the pairing with blanks is one-to-one. -->
588
+ <xsl:variable name="the-evaluation" select="ancestor::statement[1]/../evaluation"/>
589
+ <xsl:variable name="ordered-evaluates" select="$the-evaluation/evaluate[not(@all='yes')]"/>
534
590
 
535
- <xsl:if test="$blankNum > 1">
536
- <xsl:text>, </xsl:text>
537
- </xsl:if>
591
+ <!-- Pair by name when possible, else by position. -->
592
+ <xsl:variable name="named-match" select="$the-evaluation/evaluate[@name = $fillinName]"/>
593
+ <xsl:variable name="ordered-match"
594
+ select="$ordered-evaluates[position() = number($blankNum)]"/>
595
+ <xsl:variable name="the-evaluate"
596
+ select="$named-match | $ordered-match[count($named-match) = 0]"/>
597
+
598
+ <!-- The two error branches below still emit a well-formed array, so -->
599
+ <!-- that one authoring mistake costs the exercise its feedback and -->
600
+ <!-- not its JSON. The caller has already written the separator that -->
601
+ <!-- precedes this blank; emitting nothing here would leave ", ," and -->
602
+ <!-- the whole script would fail to parse. -->
538
603
  <xsl:choose>
539
- <!-- First look for a matching name. -->
540
- <xsl:when test="ancestor::statement/../evaluation/evaluate[@name = $fillinName]">
541
- <xsl:apply-templates select="ancestor::statement/../evaluation/evaluate[@name = $fillinName]" mode="dynamic-feedback">
542
- <xsl:with-param name="multiAns" select="$multiAns"/>
543
- <xsl:with-param name="match-fillin" select="."/>
544
- </xsl:apply-templates>
604
+ <!-- Author reused one @name on several "evaluate" elements. -->
605
+ <xsl:when test="count($the-evaluate) > 1">
606
+ <xsl:message>PTX:ERROR: several "evaluate" share the name "<xsl:value-of
607
+ select="$fillinName"/>" in "<xsl:apply-templates select="." mode="unique-id"/>".</xsl:message>
608
+ <xsl:text>[{"feedback": "[Error: Several evaluate elements share this blank's name]"}]</xsl:text>
545
609
  </xsl:when>
546
- <!-- Otherwise match on order. -->
547
- <xsl:when test="ancestor::statement/../evaluation/evaluate[position() = $blankNum]">
548
- <xsl:apply-templates select="ancestor::statement/../evaluation/evaluate[position() = $blankNum]" mode="dynamic-feedback">
610
+ <xsl:when test="$the-evaluate">
611
+ <!-- Only reachable on the positional path: a name match makes -->
612
+ <!-- @name and $fillinName equal by construction. -->
613
+ <!-- -->
614
+ <!-- @name on an "evaluate" exists to pair it with a "fillin" of -->
615
+ <!-- the same name, so a positional match whose names disagree -->
616
+ <!-- is reported here. -->
617
+ <xsl:if test="$the-evaluate/@name and not($the-evaluate/@name = $fillinName)">
618
+ <xsl:choose>
619
+ <!-- Names don't agree -->
620
+ <xsl:when test="@name">
621
+ <xsl:message>PTX:ERROR: blank named "<xsl:value-of select="@name"/>" of "<xsl:apply-templates
622
+ select="." mode="unique-id"/>" was matched by position to an "evaluate" named "<xsl:value-of
623
+ select="$the-evaluate/@name"/>". The names must agree, or the blank must be left unnamed.</xsl:message>
624
+ </xsl:when>
625
+ <!-- Name present for evaluate but not fillin -->
626
+ <xsl:otherwise>
627
+ <xsl:message>PTX:WARNING: the "evaluate" named "<xsl:value-of select="$the-evaluate/@name"/>" in "<xsl:apply-templates
628
+ select="." mode="unique-id"/>" was matched to blank <xsl:value-of select="$blankNum"/> by position,
629
+ because that blank has no @name. A name on an "evaluate" is only used to pair it with a "fillin"
630
+ carrying the same name; give the blank @name="<xsl:value-of select="$the-evaluate/@name"/>" to make
631
+ the pairing explicit, or drop the name from the "evaluate".</xsl:message>
632
+ </xsl:otherwise>
633
+ </xsl:choose>
634
+ </xsl:if>
635
+ <xsl:apply-templates select="$the-evaluate" mode="dynamic-feedback">
549
636
  <xsl:with-param name="multiAns" select="$multiAns"/>
550
637
  <xsl:with-param name="match-fillin" select="."/>
551
638
  </xsl:apply-templates>
552
639
  </xsl:when>
553
- <!-- No check matches: Make blank default. -->
554
640
  <xsl:otherwise>
555
- <xsl:message>PTX:ERROR: No matching #evaluate for #fillin in "<xsl:value-of select="@visible-id"/>".</xsl:message>
641
+ <xsl:message>PTX:ERROR: No matching #evaluate for #fillin in "<xsl:apply-templates
642
+ select="." mode="unique-id"/>".</xsl:message>
643
+ <xsl:text>[{"feedback": "[Error: No evaluate to match this blank]"}]</xsl:text>
556
644
  </xsl:otherwise>
557
645
  </xsl:choose>
558
646
  </xsl:template>
@@ -909,7 +997,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
909
997
  <xsl:when test="name($curTest)='mathcmp' and $curTest/@use-answer='yes'">
910
998
  <xsl:choose>
911
999
  <xsl:when test="not($fillin/@ansobj)">
912
- <xsl:message>PTX:ERROR: Feedback for "<xsl:value-of select="@visible-id"/>" says to use given math answer, but @ansobj not defined. </xsl:message>
1000
+ <xsl:message>PTX:ERROR: Feedback for "<xsl:apply-templates select="." mode="unique-id" />" says to use given math answer, but @ansobj not defined. </xsl:message>
913
1001
  <xsl:text>UNDEFINED</xsl:text>
914
1002
  </xsl:when>
915
1003
  <xsl:otherwise>
@@ -959,7 +1047,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
959
1047
  </xsl:when>
960
1048
  <xsl:when test="$logic = 'not'"/> <!-- Negation has no preparation -->
961
1049
  <xsl:otherwise>
962
- <xsl:message>PTX:ERROR: Invalid logic operator in dynamic fillin for "<xsl:value-of select="@visible-id"/>"</xsl:message>
1050
+ <xsl:message>PTX:ERROR: Invalid logic operator in dynamic fillin for "<xsl:apply-templates select="." mode="unique-id" />"</xsl:message>
963
1051
  </xsl:otherwise>
964
1052
  </xsl:choose>
965
1053
  <xsl:for-each select="$tests"> <!-- Work through the layer of tests one at a time. -->
@@ -1066,9 +1154,14 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1066
1154
  <xsl:with-param name="setupMode" select="$setupMode"/>
1067
1155
  </xsl:apply-templates>
1068
1156
  <xsl:text>, "number", {</xsl:text>
1069
- <xsl:apply-templates select="variable" mode="evaluation-binding" >
1070
- <xsl:with-param name="setupMode" select="$setupMode" />
1071
- </xsl:apply-templates>
1157
+ <xsl:for-each select="variable">
1158
+ <xsl:if test="position() > 1">
1159
+ <xsl:text>, </xsl:text>
1160
+ </xsl:if>
1161
+ <xsl:apply-templates select="." mode="evaluation-binding" >
1162
+ <xsl:with-param name="setupMode" select="$setupMode" />
1163
+ </xsl:apply-templates>
1164
+ </xsl:for-each>
1072
1165
  <xsl:text>})</xsl:text>
1073
1166
  <xsl:if test="@reduce='yes'">
1074
1167
  <xsl:text>.reduce().simplifyConstants()</xsl:text>
@@ -1157,9 +1250,14 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1157
1250
  <xsl:with-param name="setupMode" select="$setupMode"/>
1158
1251
  </xsl:apply-templates>
1159
1252
  <xsl:text>, {</xsl:text>
1160
- <xsl:apply-templates select="variable" mode="evaluation-binding" >
1161
- <xsl:with-param name="setupMode" select="$setupMode" />
1162
- </xsl:apply-templates>
1253
+ <xsl:for-each select="variable">
1254
+ <xsl:if test="position() > 1">
1255
+ <xsl:text>, </xsl:text>
1256
+ </xsl:if>
1257
+ <xsl:apply-templates select="." mode="evaluation-binding" >
1258
+ <xsl:with-param name="setupMode" select="$setupMode" />
1259
+ </xsl:apply-templates>
1260
+ </xsl:for-each>
1163
1261
  <xsl:text>})</xsl:text>
1164
1262
  <xsl:if test="@reduce='yes'">
1165
1263
  <xsl:text>.reduce().simplifyConstants()</xsl:text>
@@ -1199,9 +1297,6 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1199
1297
  <xsl:text>v.</xsl:text>
1200
1298
  </xsl:if>
1201
1299
  </xsl:variable>
1202
- <xsl:if test="position() > 1">
1203
- <xsl:text>, </xsl:text>
1204
- </xsl:if>
1205
1300
  <xsl:call-template name="quote-string">
1206
1301
  <xsl:with-param name="text" select="@name" />
1207
1302
  </xsl:call-template>
@@ -545,6 +545,14 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
545
545
  <!-- Parson (Horizontal) -->
546
546
 
547
547
  <xsl:template match="*[@pi:exercise-interactive = 'parson-horizontal']" mode="runestone-to-static">
548
+ <!-- Natural-language blocks (mathematics included) must stay in -->
549
+ <!-- the normal flow, where markup is processed; only genuine -->
550
+ <!-- program code belongs in a verbatim code display. This -->
551
+ <!-- mirrors the vertical Parsons template above. -->
552
+ <xsl:variable name="language">
553
+ <xsl:apply-templates select="." mode="get-programming-language"/>
554
+ </xsl:variable>
555
+ <xsl:variable name="b-natural" select="($language = '') or ($language = 'natural')"/>
548
556
  <xsl:attribute name="language">
549
557
  <xsl:apply-templates select="." mode="active-language"/>
550
558
  </xsl:attribute>
@@ -552,20 +560,31 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
552
560
  <!-- Statement -->
553
561
  <statement>
554
562
  <xsl:copy-of select="statement/node()"/>
555
- <!-- programming language version -->
556
563
  <p>
557
- <cd>
558
- <cline>
559
- <!-- hard to tell which is last once sorted, -->
560
- <!-- so we just mark front *and* end -->
564
+ <!-- hard to tell which is last once sorted, -->
565
+ <!-- so we just mark front *and* end -->
566
+ <xsl:choose>
567
+ <xsl:when test="$b-natural">
561
568
  <xsl:text> | </xsl:text>
562
569
  <xsl:for-each select="blocks/block[@order]">
563
570
  <xsl:sort select="@order"/>
564
- <xsl:apply-templates select="." mode="static-horizontal-block"/>
571
+ <xsl:apply-templates select="." mode="static-horizontal-block-flow"/>
565
572
  <xsl:text> | </xsl:text>
566
573
  </xsl:for-each>
567
- </cline>
568
- </cd>
574
+ </xsl:when>
575
+ <xsl:otherwise>
576
+ <cd>
577
+ <cline>
578
+ <xsl:text> | </xsl:text>
579
+ <xsl:for-each select="blocks/block[@order]">
580
+ <xsl:sort select="@order"/>
581
+ <xsl:apply-templates select="." mode="static-horizontal-block"/>
582
+ <xsl:text> | </xsl:text>
583
+ </xsl:for-each>
584
+ </cline>
585
+ </cd>
586
+ </xsl:otherwise>
587
+ </xsl:choose>
569
588
  </p>
570
589
  </statement>
571
590
  <!-- We provide a complete solution below, -->
@@ -577,22 +596,34 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
577
596
  <!-- versions on authored ones. -->
578
597
  <xsl:copy-of select="solution"/>
579
598
  <solution>
580
- <!-- programming language version -->
581
599
  <!-- filter out distractors for the solution -->
582
600
  <xsl:variable name="the-blocks" select="blocks/block[not(@correct = 'no')]"/>
583
601
  <p>
584
- <cd>
585
- <cline>
602
+ <xsl:choose>
603
+ <xsl:when test="$b-natural">
586
604
  <!-- authored in order, but need to follow @ref -->
587
605
  <xsl:for-each select="$the-blocks">
588
- <xsl:apply-templates select="." mode="static-horizontal-block"/>
589
- <!-- context shift should handle distractors at the end -->
606
+ <xsl:apply-templates select="." mode="static-horizontal-block-flow"/>
590
607
  <xsl:if test="following-sibling::block">
591
608
  <xsl:text> </xsl:text>
592
609
  </xsl:if>
593
610
  </xsl:for-each>
594
- </cline>
595
- </cd>
611
+ </xsl:when>
612
+ <xsl:otherwise>
613
+ <cd>
614
+ <cline>
615
+ <!-- authored in order, but need to follow @ref -->
616
+ <xsl:for-each select="$the-blocks">
617
+ <xsl:apply-templates select="." mode="static-horizontal-block"/>
618
+ <!-- context shift should handle distractors at the end -->
619
+ <xsl:if test="following-sibling::block">
620
+ <xsl:text> </xsl:text>
621
+ </xsl:if>
622
+ </xsl:for-each>
623
+ </cline>
624
+ </cd>
625
+ </xsl:otherwise>
626
+ </xsl:choose>
596
627
  </p>
597
628
  </solution>
598
629
  </xsl:template>
@@ -610,6 +641,24 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
610
641
  </xsl:choose>
611
642
  </xsl:template>
612
643
 
644
+ <!-- The flow variant serves natural-language blocks: the children -->
645
+ <!-- of a block are "p", whose contents join the running line, so -->
646
+ <!-- mathematics and other markup process normally. -->
647
+ <!-- A natural-language block may wrap its content in a "p", or -->
648
+ <!-- carry short inline content directly; the flow copy handles -->
649
+ <!-- both shapes, following @ref to a reused source block first -->
650
+ <xsl:template match="blocks/block" mode="static-horizontal-block-flow">
651
+ <xsl:variable name="the-block" select="id(@ref)|self::*[not(@ref)]"/>
652
+ <xsl:choose>
653
+ <xsl:when test="$the-block/p">
654
+ <xsl:copy-of select="$the-block/p/node()"/>
655
+ </xsl:when>
656
+ <xsl:otherwise>
657
+ <xsl:copy-of select="$the-block/node()"/>
658
+ </xsl:otherwise>
659
+ </xsl:choose>
660
+ </xsl:template>
661
+
613
662
  <!-- Cardsort and Matching Problems -->
614
663
 
615
664
  <!-- Cardsort problems are (roughly) functions, while a (general) -->
@@ -1172,23 +1221,26 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1172
1221
 
1173
1222
  <xsl:template match="statement" mode="fillin-solution">
1174
1223
  <xsl:variable name="exercise" select=".."/>
1224
+ <xsl:variable name="ordered-evaluates" select="$exercise/evaluation/evaluate[not(@all = 'yes')]"/>
1175
1225
  <solution>
1176
1226
  <xsl:apply-templates select="node()|@*" mode="fillin-solution"/>
1177
1227
  <!-- xerox feedback for correct response on each var -->
1178
1228
  <xsl:for-each select="../setup/var/condition[1]/feedback">
1179
1229
  <xsl:apply-templates select="node()" mode="fillin-solution"/>
1180
1230
  </xsl:for-each>
1181
- <xsl:for-each select=".//fillin[@answer]">
1231
+ <xsl:for-each select=".//fillin">
1182
1232
  <xsl:variable name="fillin-name" select="@name"/>
1183
1233
  <xsl:variable name="fillin-pos" select="position()"/>
1234
+ <xsl:variable name="named-evaluate" select="$exercise/evaluation/evaluate[@name = $fillin-name]"/>
1235
+ <xsl:variable name="ordered-evaluate" select="$ordered-evaluates[position() = $fillin-pos]"/>
1184
1236
  <xsl:choose>
1185
1237
  <!-- If #evaluate matches by name, find feedback on a correct result -->
1186
- <xsl:when test="$exercise/evaluation/evaluate[@name='$fillin-name']/test[@correct='yes']">
1187
- <xsl:apply-templates select="$exercise/evaluation/evaluate[@name='$fillin-name']/test[@correct='yes']/feedback/node()" mode="fillin-solution"/>
1238
+ <xsl:when test="$named-evaluate/test[@correct = 'yes']">
1239
+ <xsl:apply-templates select="$named-evaluate/test[@correct = 'yes']/feedback/node()" mode="fillin-solution"/>
1188
1240
  </xsl:when>
1189
1241
  <!-- Otherwise #evaluate matches by order, find feedback on a correct result -->
1190
- <xsl:when test="$exercise/evaluation/evaluate[$fillin-pos]/test[@correct='yes']">
1191
- <xsl:apply-templates select="$exercise/evaluation/evaluate[$fillin-pos]/test[@correct='yes']/feedback/node()" mode="fillin-solution"/>
1242
+ <xsl:when test="$ordered-evaluate/test[@correct = 'yes']">
1243
+ <xsl:apply-templates select="$ordered-evaluate/test[@correct = 'yes']/feedback/node()" mode="fillin-solution"/>
1192
1244
  </xsl:when>
1193
1245
  </xsl:choose>
1194
1246
  </xsl:for-each>