@pretextbook/pretext-html 0.3.0 → 0.5.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 (58) hide show
  1. package/README.md +106 -10
  2. package/assets/preview-html.xsl +8 -4
  3. package/assets/preview-revealjs.xsl +85 -0
  4. package/assets/upstream.json +1 -1
  5. package/assets/xsl/LICENSE-pretext +16 -0
  6. package/assets/xsl/README.md +25 -24
  7. package/assets/xsl/entities.ent +27 -0
  8. package/assets/xsl/extract-biblio-csl.xsl +6 -4
  9. package/assets/xsl/extract-dynamic.xsl +14 -12
  10. package/assets/xsl/extract-interactive.xsl +2 -2
  11. package/assets/xsl/extract-pg.xsl +123 -306
  12. package/assets/xsl/extract-qrcode.xsl +12 -2
  13. package/assets/xsl/extract-sageplot.xsl +1 -1
  14. package/assets/xsl/extract-trace.xsl +3 -3
  15. package/assets/xsl/extract-youtube.xsl +1 -1
  16. package/assets/xsl/latex/pretext-latex-texstyle.xsl +4 -5
  17. package/assets/xsl/localizations/README.md +24 -24
  18. package/assets/xsl/pretext-assembly.xsl +463 -368
  19. package/assets/xsl/pretext-beamer.xsl +43 -146
  20. package/assets/xsl/pretext-braille-preprint.xsl +458 -202
  21. package/assets/xsl/pretext-common.xsl +486 -510
  22. package/assets/xsl/pretext-epub.xsl +318 -78
  23. package/assets/xsl/pretext-fo.xsl +80 -96
  24. package/assets/xsl/pretext-html.xsl +413 -318
  25. package/assets/xsl/pretext-jupyter.xsl +534 -322
  26. package/assets/xsl/pretext-latex-classic.xsl +14 -15
  27. package/assets/xsl/pretext-latex-common.xsl +393 -2397
  28. package/assets/xsl/pretext-latex.xsl +1995 -5
  29. package/assets/xsl/pretext-markdown.xsl +919 -0
  30. package/assets/xsl/pretext-numbers.xsl +57 -39
  31. package/assets/xsl/pretext-revealjs.xsl +241 -33
  32. package/assets/xsl/pretext-runestone-fitb.xsl +34 -35
  33. package/assets/xsl/pretext-runestone-static.xsl +17 -17
  34. package/assets/xsl/pretext-runestone.xsl +36 -34
  35. package/assets/xsl/pretext-sage-doctest.xsl +2 -2
  36. package/assets/xsl/pretext-text-utilities.xsl +69 -1
  37. package/assets/xsl/pretext-text.xsl +1077 -107
  38. package/assets/xsl/pretext-view-source.xsl +5 -3
  39. package/assets/xsl/pretext-ww-problem-sets.xsl +6 -1
  40. package/assets/xsl/publisher-variables.xsl +397 -477
  41. package/assets/xsl/support/play-button/README.md +1 -3
  42. package/assets/xsl/tests/README.md +1 -1
  43. package/assets/xsl/utilities/README.md +6 -8
  44. package/assets/xsl/utilities/report-publisher-variables.xsl +15 -0
  45. package/assets/xsl-bundle.json +1 -1
  46. package/dist/cli-DZsyZERX.js +694 -0
  47. package/dist/cli.js +1 -1
  48. package/dist/index.browser.d.ts +5 -0
  49. package/dist/index.browser.js +499 -344
  50. package/dist/index.d.ts +5 -0
  51. package/dist/index.js +23 -18
  52. package/dist/publication.d.ts +26 -12
  53. package/dist/renderer.d.ts +68 -0
  54. package/dist/reveal.d.ts +77 -0
  55. package/dist/reveal.js +110 -0
  56. package/dist/target.d.ts +34 -0
  57. package/package.json +12 -1
  58. package/dist/cli-CzoinNle.js +0 -639
@@ -5,10 +5,11 @@
5
5
  <xsl:stylesheet
6
6
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
7
7
  xmlns:xml="http://www.w3.org/XML/1998/namespace"
8
+ xmlns:pi="http://pretextbook.org/2020/pretext/internal"
8
9
  xmlns:exsl="http://exslt.org/common"
9
10
  xmlns:date="http://exslt.org/dates-and-times"
10
11
  xmlns:str="http://exslt.org/strings"
11
- extension-element-prefixes="exsl date str"
12
+ extension-element-prefixes="pi exsl date str"
12
13
  >
13
14
 
14
15
  <xsl:variable name="b-include-postContent" select="true()"/>
@@ -18,12 +19,12 @@
18
19
  <!-- ==================================================== -->
19
20
 
20
21
  <!-- Convert fillin tag to an input element on the page -->
21
- <xsl:template match="exercise[@exercise-interactive='fillin']//fillin
22
- | project[@exercise-interactive='fillin']//fillin
23
- | activity[@exercise-interactive='fillin']//fillin
24
- | exploration[@exercise-interactive='fillin']//fillin
25
- | investigation[@exercise-interactive='fillin']//fillin
26
- | task[@exercise-interactive='fillin']//fillin">
22
+ <xsl:template match="exercise[@pi:exercise-interactive='fillin']//fillin
23
+ | project[@pi:exercise-interactive='fillin']//fillin
24
+ | activity[@pi:exercise-interactive='fillin']//fillin
25
+ | exploration[@pi:exercise-interactive='fillin']//fillin
26
+ | investigation[@pi:exercise-interactive='fillin']//fillin
27
+ | task[@pi:exercise-interactive='fillin']//fillin">
27
28
  <xsl:param name="b-human-readable" />
28
29
  <xsl:variable name="parent-id">
29
30
  <xsl:apply-templates select="ancestor::exercise" mode="html-id" />
@@ -61,12 +62,12 @@
61
62
  <!-- The HTML will contain this JSON and Runestone extracts it -->
62
63
  <!-- and inserts it into the HTML page via JS. -->
63
64
  <!-- ========================================================= -->
64
- <xsl:template match="exercise[@exercise-interactive='fillin']
65
- | project[@exercise-interactive='fillin']
66
- | activity[@exercise-interactive='fillin']
67
- | exploration[@exercise-interactive='fillin']
68
- | investigation[@exercise-interactive='fillin']
69
- | task[@exercise-interactive='fillin']" mode="runestone-to-interactive">
65
+ <xsl:template match="exercise[@pi:exercise-interactive='fillin']
66
+ | project[@pi:exercise-interactive='fillin']
67
+ | activity[@pi:exercise-interactive='fillin']
68
+ | exploration[@pi:exercise-interactive='fillin']
69
+ | investigation[@pi:exercise-interactive='fillin']
70
+ | task[@pi:exercise-interactive='fillin']" mode="runestone-to-interactive">
70
71
  <xsl:variable name="b-is-dynamic" select="boolean(./setup)"/>
71
72
  <div class="ptx-runestone-container">
72
73
  <div class="runestone">
@@ -83,7 +84,7 @@
83
84
  </xsl:when>
84
85
  <xsl:otherwise>
85
86
  <!-- Report if a seed is not provided-->
86
- <xsl:message>PTX:WARNING: Dynamic exercise "<xsl:value-of select="@visible-id"/>" is missing setup @seed for static content generation.</xsl:message>
87
+ <xsl:message>PTX:FALLBACK: Dynamic exercise "<xsl:value-of select="@visible-id"/>" is missing setup @seed for static content generation.</xsl:message>
87
88
  <xsl:text>1234</xsl:text>
88
89
  </xsl:otherwise>
89
90
  </xsl:choose>
@@ -421,42 +422,32 @@
421
422
  </xsl:apply-templates>
422
423
  </xsl:when>
423
424
  <!-- If no explicit test is provided, use given answer. -->
425
+ <!-- NB: The @answer cases (mode='number' and mode='string') are now -->
426
+ <!-- handled upstream in pretext-assembly.xsl (exercise pass), which -->
427
+ <!-- injects a synthesized <test correct="yes"> element. -->
428
+ <!-- The remaining cases are for fillins that use @ansobj that -->
429
+ <!-- reference an object that was dynamically created (random). -->
424
430
  <xsl:otherwise>
425
431
  <xsl:text>{</xsl:text>
426
432
  <xsl:choose>
427
- <xsl:when test="$match-fillin/@answer">
428
- <xsl:choose>
429
- <xsl:when test="$match-fillin/@mode='number'">
430
- <xsl:text>"number": [</xsl:text>
431
- <xsl:value-of select="$match-fillin/@answer"/>
432
- <xsl:text>,</xsl:text>
433
- <xsl:value-of select="$match-fillin/@answer"/>
434
- <xsl:text>]</xsl:text>
435
- </xsl:when>
436
- <xsl:when test="$match-fillin/@mode='string'">
437
- <xsl:text>"regex": "</xsl:text>
438
- <xsl:value-of select="$match-fillin/@answer"/>
439
- <xsl:text>"</xsl:text>
440
- </xsl:when>
441
- <xsl:otherwise>
442
- <xsl:message>PTX:ERROR: fillin has an @answer with invalid or missing mode (valid: number or string) in "<xsl:value-of select="@visible-id"/>. If dynamic, you should use @ansobj.".</xsl:message>
443
- </xsl:otherwise>
444
- </xsl:choose>
445
- </xsl:when>
446
433
  <xsl:when test="$match-fillin/@ansobj">
447
434
  <xsl:choose>
435
+ <!-- Number objects — assume match with very tight tolerance -->
448
436
  <xsl:when test="$match-fillin/@mode='number'">
449
437
  <xsl:text>function() {&#xa;</xsl:text>
450
438
  <xsl:text> return (Math.abs(</xsl:text>
451
439
  <xsl:value-of select="$match-fillin/@ansobj"/>
452
440
  <xsl:text>- ans) &lt; 1e-10);&#xa;}</xsl:text>
453
441
  </xsl:when>
442
+ <!-- String objects — assume require exact string match -->
443
+ <!-- otherwise the author should specify the test -->
454
444
  <xsl:when test="$match-fillin/@mode='string'">
455
445
  <xsl:text>function() {&#xa;</xsl:text>
456
446
  <xsl:text> return (</xsl:text>
457
447
  <xsl:value-of select="$match-fillin/@ansobj"/>
458
448
  <xsl:text>== ans);&#xa;}</xsl:text>
459
449
  </xsl:when>
450
+ <!-- Dynamic math objects: compare expressions -->
460
451
  <xsl:when test="$match-fillin/@mode='math'">
461
452
  <xsl:text>function() {&#xa;</xsl:text>
462
453
  <xsl:text> return _mobjs.compareExpressions(</xsl:text>
@@ -717,8 +708,16 @@
717
708
  <xsl:otherwise>
718
709
  <xsl:variable name="answer">
719
710
  <xsl:choose>
711
+ <!-- If comparing with actual answer, implicitly a literal check -->
720
712
  <xsl:when test="strcmp/@use-answer='yes'">
721
- <xsl:value-of select="$fillin/@answer"/>
713
+ <xsl:call-template name="escape-regexp-literal">
714
+ <xsl:with-param name="text" select="$fillin/@answer"/>
715
+ </xsl:call-template>
716
+ </xsl:when>
717
+ <xsl:when test="strcmp/@literal='yes'">
718
+ <xsl:call-template name="escape-regexp-literal">
719
+ <xsl:with-param name="text" select="strcmp"/>
720
+ </xsl:call-template>
722
721
  </xsl:when>
723
722
  <xsl:otherwise>
724
723
  <xsl:value-of select="strcmp"/>
@@ -892,7 +891,7 @@
892
891
  <xsl:when test="name($curTest)='mathcmp' and $curTest/@use-answer='yes'">
893
892
  <xsl:choose>
894
893
  <xsl:when test="not($fillin/@ansobj)">
895
- <xsl:message>PTX:WARNING: Feedback for "<xsl:value-of select="@visible-id"/>" says to use given math answer, but @ansobj not defined. </xsl:message>
894
+ <xsl:message>PTX:ERROR: Feedback for "<xsl:value-of select="@visible-id"/>" says to use given math answer, but @ansobj not defined. </xsl:message>
896
895
  <xsl:text>UNDEFINED</xsl:text>
897
896
  </xsl:when>
898
897
  <xsl:otherwise>
@@ -47,11 +47,11 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
47
47
  <!-- before these templates are applied, so these should just -->
48
48
  <!-- produce the "body" of the exercise. -->
49
49
 
50
- <!-- The application of the "runestone-to-static" template is -->
51
- <!-- controlled by a surrounding "match" that limits elements -->
52
- <!-- to "exercise", PROJECT-LIKE, and soon "task". So the -->
53
- <!-- matches here are fine with a *[@exercise-interactive='foo'], -->
54
- <!-- as a convenience. -->
50
+ <!-- The application of the "runestone-to-static" template is -->
51
+ <!-- controlled by a surrounding "match" that limits elements -->
52
+ <!-- to "exercise", PROJECT-LIKE, and soon "task". So the -->
53
+ <!-- matches here are fine with a *[@pi:exercise-interactive='foo'], -->
54
+ <!-- as a convenience. -->
55
55
 
56
56
  <!-- These get-programming-language templates duplicate logic from pretext-common -->
57
57
  <!-- as the contents of that file are not available yet. -->
@@ -66,7 +66,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
66
66
  </xsl:choose>
67
67
  </xsl:template>
68
68
 
69
- <xsl:template match="*[@exercise-interactive = 'parson' or @exercise-interactive = 'parson-horizontal']" mode="get-programming-language">
69
+ <xsl:template match="*[@pi:exercise-interactive = 'parson' or @pi:exercise-interactive = 'parson-horizontal']" mode="get-programming-language">
70
70
  <xsl:choose>
71
71
  <xsl:when test="@language">
72
72
  <xsl:value-of select="@language" />
@@ -83,7 +83,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
83
83
 
84
84
  <!-- True/False -->
85
85
 
86
- <xsl:template match="*[@exercise-interactive = 'truefalse']" mode="runestone-to-static">
86
+ <xsl:template match="*[@pi:exercise-interactive = 'truefalse']" mode="runestone-to-static">
87
87
  <!-- metadata (idx, title) -->
88
88
  <xsl:copy-of select="statement/preceding-sibling::*"/>
89
89
  <!-- prompt, followed by ordered list of choices -->
@@ -149,7 +149,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
149
149
  </solution>
150
150
  </xsl:template>
151
151
 
152
- <xsl:template match="*[@exercise-interactive = 'multiplechoice']" mode="runestone-to-static">
152
+ <xsl:template match="*[@pi:exercise-interactive = 'multiplechoice']" mode="runestone-to-static">
153
153
  <!-- metadata (idx, title) -->
154
154
  <xsl:copy-of select="statement/preceding-sibling::*"/>
155
155
  <!-- prompt, followed by ordered list of choices -->
@@ -215,7 +215,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
215
215
  </solution>
216
216
  </xsl:template>
217
217
 
218
- <xsl:template match="*[@exercise-interactive = 'parson']" mode="runestone-to-static">
218
+ <xsl:template match="*[@pi:exercise-interactive = 'parson']" mode="runestone-to-static">
219
219
  <!-- determine these options before context switches -->
220
220
  <xsl:variable name="language">
221
221
  <!-- we just need the "raw" programming language, not active-language translation -->
@@ -532,7 +532,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
532
532
 
533
533
  <!-- Parson (Horizontal) -->
534
534
 
535
- <xsl:template match="*[@exercise-interactive = 'parson-horizontal']" mode="runestone-to-static">
535
+ <xsl:template match="*[@pi:exercise-interactive = 'parson-horizontal']" mode="runestone-to-static">
536
536
  <xsl:attribute name="language">
537
537
  <xsl:apply-templates select="." mode="active-language"/>
538
538
  </xsl:attribute>
@@ -610,7 +610,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
610
610
 
611
611
  <!-- Note how this template accomodates both types of problems -->
612
612
  <!-- by using match/select and modal template names effectively. -->
613
- <xsl:template match="*[@exercise-interactive = 'cardsort']|*[@exercise-interactive = 'matching']" mode="runestone-to-static">
613
+ <xsl:template match="*[@pi:exercise-interactive = 'cardsort']|*[@pi:exercise-interactive = 'matching']" mode="runestone-to-static">
614
614
  <!-- metadata (idx, title) -->
615
615
  <xsl:copy-of select="statement/preceding-sibling::*"/>
616
616
  <!-- Statement -->
@@ -826,7 +826,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
826
826
 
827
827
  <!-- Clickable Area -->
828
828
 
829
- <xsl:template match="*[@exercise-interactive = 'clickablearea']" mode="runestone-to-static">
829
+ <xsl:template match="*[@pi:exercise-interactive = 'clickablearea']" mode="runestone-to-static">
830
830
  <!-- metadata (idx, title) -->
831
831
  <xsl:copy-of select="statement/preceding-sibling::*"/>
832
832
  <!-- Statement -->
@@ -989,7 +989,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
989
989
 
990
990
  <!-- Select -->
991
991
 
992
- <xsl:template match="*[@exercise-interactive = 'select']" mode="runestone-to-static">
992
+ <xsl:template match="*[@pi:exercise-interactive = 'select']" mode="runestone-to-static">
993
993
  <!-- metadata (idx, title) -->
994
994
  <xsl:copy-of select="select/preceding-sibling::*"/>
995
995
 
@@ -1101,7 +1101,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1101
1101
 
1102
1102
  <!-- Fill-In the Blanks (Basic) -->
1103
1103
 
1104
- <xsl:template match="*[@exercise-interactive = 'fillin-basic']" mode="runestone-to-static">
1104
+ <xsl:template match="*[@pi:exercise-interactive = 'fillin-basic']" mode="runestone-to-static">
1105
1105
  <!-- metadata (idx, title) -->
1106
1106
  <xsl:copy-of select="statement/preceding-sibling::*"/>
1107
1107
  <!-- reproduce statement identically, but replace var w/ fillin -->
@@ -1212,7 +1212,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1212
1212
 
1213
1213
  <!-- Fill-In the Blanks (Complete) -->
1214
1214
 
1215
- <xsl:template match="*[@exercise-interactive = 'fillin']" mode="runestone-to-static">
1215
+ <xsl:template match="*[@pi:exercise-interactive = 'fillin']" mode="runestone-to-static">
1216
1216
  <!-- metadata (idx, title) -->
1217
1217
  <xsl:copy-of select="statement/preceding-sibling::*"/>
1218
1218
  <!-- reproduce statement identically, but replace var w/ fillin -->
@@ -1268,7 +1268,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1268
1268
  <!-- Short Answer -->
1269
1269
 
1270
1270
  <!-- Authored with a "response" element, we effectively drop it here -->
1271
- <xsl:template match="*[@exercise-interactive = 'shortanswer']" mode="runestone-to-static">
1271
+ <xsl:template match="*[@pi:exercise-interactive = 'shortanswer']" mode="runestone-to-static">
1272
1272
  <!-- metadata (idx, title) -->
1273
1273
  <xsl:copy-of select="statement/preceding-sibling::*"/>
1274
1274
  <!-- reproduce usual components -->
@@ -1345,7 +1345,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1345
1345
 
1346
1346
  <!-- Active Code -->
1347
1347
 
1348
- <xsl:template match="*[@exercise-interactive = 'coding']" mode="runestone-to-static">
1348
+ <xsl:template match="*[@pi:exercise-interactive = 'coding']" mode="runestone-to-static">
1349
1349
  <!-- metadata (idx, title) -->
1350
1350
  <xsl:copy-of select="statement/preceding-sibling::*"/>
1351
1351
  <statement>
@@ -751,7 +751,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
751
751
  <!-- efficient but has proven to be a popular spot for bugs. -->
752
752
  <xsl:template match="exercise|&PROJECT-LIKE;|task" mode="runestone-manifest">
753
753
  <xsl:variable name="manifestable-interactives-fenced">|truefalse|multiplechoice|parson|parson-horizontal|cardsort|matching|clickablearea|select|fillin-basic|fillin|coding|dual|shortanswer|webwork|</xsl:variable>
754
- <xsl:if test="contains($manifestable-interactives-fenced, concat('|', @exercise-interactive, '|'))">
754
+ <xsl:if test="contains($manifestable-interactives-fenced, concat('|', @pi:exercise-interactive, '|'))">
755
755
  <question>
756
756
  <!-- A divisional exercise ("exercises/../exercise") is not really -->
757
757
  <!-- a reading activity in the Runestone model, so we flag these -->
@@ -762,8 +762,8 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
762
762
  <!-- value to "yes" and never bother to say "no". The only -->
763
763
  <!-- consumer is the import into the Runestone database, so any -->
764
764
  <!-- change needs only coordinate there. -->
765
- <xsl:if test="(@exercise-customization = 'divisional') or
766
- (self::task and ancestor::exercise[@exercise-customization = 'divisional'])">
765
+ <xsl:if test="(@pi:exercise-customization = 'divisional') or
766
+ (self::task and ancestor::exercise[@pi:exercise-customization = 'divisional'])">
767
767
  <xsl:attribute name="optional">
768
768
  <xsl:text>yes</xsl:text>
769
769
  </xsl:attribute>
@@ -779,7 +779,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
779
779
  <xsl:apply-templates select="." mode="eg-introduction"/>
780
780
  <xsl:choose>
781
781
  <!-- with "webwork" guts, the HTML is exceptional -->
782
- <xsl:when test="@exercise-interactive = 'webwork'">
782
+ <xsl:when test="@pi:exercise-interactive = 'webwork'">
783
783
  <xsl:apply-templates select="." mode="webwork-core">
784
784
  <xsl:with-param name="b-original" select="true()"/>
785
785
  <xsl:with-param name="heading-level" select="3"/>
@@ -814,13 +814,13 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
814
814
  </htmlsrc>
815
815
  </question>
816
816
  </xsl:if>
817
- <!-- The match for this template will include "exercise" and &PROJECT-LIKE -->
818
- <!-- that are just containers for a bunch of "task". In other words, they -->
819
- <!-- will not be marked with the "@exercise-interactive" attribute. So the -->
820
- <!-- "xsl:if" above will fail. And right here is a dead-end. We need to -->
821
- <!-- recurse into "task" for the possibility they are marked with -->
822
- <!-- "@exercise-interactive" so they can potentially get placed properly in -->
823
- <!-- the manifest. -->
817
+ <!-- The match for this template will include "exercise" and &PROJECT-LIKE -->
818
+ <!-- that are just containers for a bunch of "task". In other words, they -->
819
+ <!-- will not be marked with the "@pi:exercise-interactive" attribute. So the -->
820
+ <!-- "xsl:if" above will fail. And right here is a dead-end. We need to -->
821
+ <!-- recurse into "task" for the possibility they are marked with -->
822
+ <!-- "@pi:exercise-interactive" so they can potentially get placed properly in -->
823
+ <!-- the manifest. -->
824
824
  <xsl:apply-templates select="task" mode="runestone-manifest"/>
825
825
  </xsl:template>
826
826
 
@@ -987,15 +987,15 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
987
987
  <!-- "regular" PreTeXt statement together with some additional -->
988
988
  <!-- interactive material to make a hybrid "statement" -->
989
989
 
990
- <!-- The application of the "runestone-to-interactive" template is -->
991
- <!-- controlled by a surrounding "match" that limits elements -->
992
- <!-- to "exercise", PROJECT-LIKE, and soon "task". So the -->
993
- <!-- matches here are fine with a *[@exercise-interactive='foo'], -->
994
- <!-- as a convenience. -->
990
+ <!-- The application of the "runestone-to-interactive" template is -->
991
+ <!-- controlled by a surrounding "match" that limits elements -->
992
+ <!-- to "exercise", PROJECT-LIKE, and soon "task". So the -->
993
+ <!-- matches here are fine with a *[@pi:exercise-interactive='foo'], -->
994
+ <!-- as a convenience. -->
995
995
 
996
996
  <!-- True/False -->
997
997
 
998
- <xsl:template match="*[@exercise-interactive = 'truefalse']" mode="runestone-to-interactive">
998
+ <xsl:template match="*[@pi:exercise-interactive = 'truefalse']" mode="runestone-to-interactive">
999
999
  <div class="ptx-runestone-container">
1000
1000
  <div class="runestone multiplechoice_section">
1001
1001
  <!-- ul can have multiple answer attribute -->
@@ -1051,7 +1051,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1051
1051
 
1052
1052
  <!-- Multiple Choice -->
1053
1053
 
1054
- <xsl:template match="*[@exercise-interactive = 'multiplechoice']" mode="runestone-to-interactive">
1054
+ <xsl:template match="*[@pi:exercise-interactive = 'multiplechoice']" mode="runestone-to-interactive">
1055
1055
  <div class="ptx-runestone-container">
1056
1056
  <div class="runestone multiplechoice_section">
1057
1057
  <!-- overall statement, not per-choice -->
@@ -1126,7 +1126,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1126
1126
 
1127
1127
  <!-- Parsons Problem -->
1128
1128
 
1129
- <xsl:template match="*[@exercise-interactive = 'parson']" mode="runestone-to-interactive">
1129
+ <xsl:template match="*[@pi:exercise-interactive = 'parson']" mode="runestone-to-interactive">
1130
1130
  <!-- active-language only used if runnable but needed multiple places -->
1131
1131
  <xsl:variable name="active-language">
1132
1132
  <xsl:apply-templates select="." mode="active-language"/>
@@ -1154,7 +1154,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1154
1154
  <xsl:variable name="id">
1155
1155
  <xsl:apply-templates select="." mode="unique-id"/>
1156
1156
  </xsl:variable>
1157
- <xsl:message>PTX:WARNING: Parsons problems need a @langauge that is a valid activecode language to be runnable</xsl:message>
1157
+ <xsl:message>PTX:WARNING: Parsons problems need a @language that is a valid activecode language to be runnable</xsl:message>
1158
1158
  <xsl:message> id: <xsl:value-of select="$id"></xsl:value-of></xsl:message>
1159
1159
  </xsl:otherwise>
1160
1160
  </xsl:choose>
@@ -1392,7 +1392,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1392
1392
 
1393
1393
  <!-- Parsons Problem (Horizontal)-->
1394
1394
 
1395
- <xsl:template match="*[@exercise-interactive = 'parson-horizontal']" mode="runestone-to-interactive">
1395
+ <xsl:template match="*[@pi:exercise-interactive = 'parson-horizontal']" mode="runestone-to-interactive">
1396
1396
  <!-- determine these options before context switches -->
1397
1397
  <xsl:variable name="active-language">
1398
1398
  <xsl:apply-templates select="." mode="active-language"/>
@@ -1617,7 +1617,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1617
1617
 
1618
1618
  <!-- Carsort Problem -->
1619
1619
 
1620
- <xsl:template match="*[@exercise-interactive = 'cardsort']" mode="runestone-to-interactive">
1620
+ <xsl:template match="*[@pi:exercise-interactive = 'cardsort']" mode="runestone-to-interactive">
1621
1621
  <div class="ptx-runestone-container">
1622
1622
  <div class="runestone cardsort_section">
1623
1623
  <ul data-component="dragndrop" data-question_label="" style="visibility: hidden;">
@@ -1683,7 +1683,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1683
1683
 
1684
1684
  <!-- Matching Problem -->
1685
1685
 
1686
- <xsl:template match="*[@exercise-interactive = 'matching']" mode="runestone-to-interactive">
1686
+ <xsl:template match="*[@pi:exercise-interactive = 'matching']" mode="runestone-to-interactive">
1687
1687
  <div class="ptx-runestone-container">
1688
1688
  <div data-component="matching" class="runestone">
1689
1689
  <xsl:apply-templates select="." mode="runestone-id-attribute"/>
@@ -1786,7 +1786,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1786
1786
 
1787
1787
  <!-- Clickable Area Problem -->
1788
1788
 
1789
- <xsl:template match="*[@exercise-interactive = 'clickablearea']" mode="runestone-to-interactive">
1789
+ <xsl:template match="*[@pi:exercise-interactive = 'clickablearea']" mode="runestone-to-interactive">
1790
1790
  <div class="ptx-runestone-container">
1791
1791
  <div class="runestone clickablearea_section">
1792
1792
  <div data-component="clickablearea" data-question_label="" style="visibility: hidden;">
@@ -1864,7 +1864,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1864
1864
  <!-- * Question List - several equivalent problems, -->
1865
1865
  <!-- reader is assigned just one (good for exams) -->
1866
1866
  <!-- * A/B Experiment - two choices, experiment managed by Runestone -->
1867
- <xsl:template match="*[@exercise-interactive = 'select']" mode="runestone-to-interactive">
1867
+ <xsl:template match="*[@pi:exercise-interactive = 'select']" mode="runestone-to-interactive">
1868
1868
  <!-- identify the type of "select" -->
1869
1869
  <!-- duplicated in "pretext-runestone-static.xsl" -->
1870
1870
  <xsl:variable name="select-variant">
@@ -1946,7 +1946,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1946
1946
  <!-- Fill-in-the-Blanks problem -->
1947
1947
 
1948
1948
  <!-- Runestone structure -->
1949
- <xsl:template match="*[@exercise-interactive = 'fillin-basic']" mode="runestone-to-interactive">
1949
+ <xsl:template match="*[@pi:exercise-interactive = 'fillin-basic']" mode="runestone-to-interactive">
1950
1950
  <div class="ptx-runestone-container">
1951
1951
  <div class="runestone fillintheblank_section">
1952
1952
  <!-- dropped "visibility: hidden" on next div -->
@@ -2093,7 +2093,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
2093
2093
 
2094
2094
  <!-- Coding exercise -->
2095
2095
 
2096
- <xsl:template match="*[@exercise-interactive = 'coding']" mode="runestone-to-interactive">
2096
+ <xsl:template match="*[@pi:exercise-interactive = 'coding']" mode="runestone-to-interactive">
2097
2097
  <!-- We don't have a 'coding' attribute value -->
2098
2098
  <!-- unless one of the two tests below is true -->
2099
2099
  <xsl:choose>
@@ -2114,7 +2114,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
2114
2114
  <!-- Dual Form exercise (dynamic/static)-->
2115
2115
 
2116
2116
  <!-- 2025-11-11: Runestone HTML is speculative -->
2117
- <xsl:template match="*[@exercise-interactive = 'dual']" mode="runestone-to-interactive">
2117
+ <xsl:template match="*[@pi:exercise-interactive = 'dual']" mode="runestone-to-interactive">
2118
2118
  <div class="ptx-runestone-container">
2119
2119
  <div class="runestone dualquestion_section">
2120
2120
  <div data-component="dual">
@@ -2135,7 +2135,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
2135
2135
  <!-- interactive, see "static" v. "dynamic" publisher variables. -->
2136
2136
  <!-- NB - not currently applying to short-form with no "statement" -->
2137
2137
  <!-- NB: match is recycled in manifest formation -->
2138
- <xsl:template match="*[@exercise-interactive = 'shortanswer']" mode="runestone-to-interactive">
2138
+ <xsl:template match="*[@pi:exercise-interactive = 'shortanswer']" mode="runestone-to-interactive">
2139
2139
  <xsl:choose>
2140
2140
  <xsl:when test="$b-host-runestone or ($short-answer-responses = 'always')">
2141
2141
  <!-- when "response" has attributes, perhaps they get interpreted here -->
@@ -2413,7 +2413,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
2413
2413
  <xsl:if test="tests/iotest">
2414
2414
  <xsl:choose>
2415
2415
  <xsl:when test="not(normalize-space(tests/text()) = '')">
2416
- <xsl:message>WARNING: You can either write text based tests or use iotests, but not both. iotests ignored in <xsl:value-of select="$rsid"/>.</xsl:message>
2416
+ <xsl:message>PTX:FALLBACK: You can either write text based tests or use iotests, but not both. iotests ignored in <xsl:value-of select="$rsid"/>.</xsl:message>
2417
2417
  </xsl:when>
2418
2418
  <xsl:otherwise>
2419
2419
  <xsl:text>===iotests===&#x0a;</xsl:text>
@@ -2870,7 +2870,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
2870
2870
  <!-- Runestone Components play nicely with this device, along with more -->
2871
2871
  <!-- boring exercises. -->
2872
2872
 
2873
- <xsl:template match="exercise[task and not(@exercise-customization = 'worksheet')]|&PROJECT-LIKE;" mode="tabbed-tasks">
2873
+ <xsl:template match="exercise[task and not(@pi:exercise-customization = 'worksheet')]|&PROJECT-LIKE;" mode="tabbed-tasks">
2874
2874
  <xsl:param name="heading-level"/>
2875
2875
  <div class="ptx-runestone-container">
2876
2876
  <div>
@@ -3037,7 +3037,9 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
3037
3037
  <!-- frequently point to other Runestone components in the database. -->
3038
3038
  <!-- * Authors point in their source with @xml:id -->
3039
3039
  <!-- values in a space- or comma- separated list -->
3040
- <!-- * We locate the targets in the orginal source -->
3040
+ <!-- * We locate the targets in the assembled tree, where a -->
3041
+ <!-- database id (a @label) exists even when only an @xml:id -->
3042
+ <!-- was authored (a backward-compatibility promotion) -->
3041
3043
  <!-- * Compute the Runestone database id -->
3042
3044
  <!-- * Return a list (varying separator) to use in Runestone HTML. -->
3043
3045
  <xsl:template name="runestone-targets">
@@ -3053,7 +3055,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
3053
3055
  <xsl:value-of select="."/>
3054
3056
  </xsl:variable>
3055
3057
  <!-- context shift so id() functions properly -->
3056
- <xsl:for-each select="$original">
3058
+ <xsl:for-each select="$root">
3057
3059
  <xsl:variable name="target" select="id($the-id)"/>
3058
3060
  <xsl:if test="not($target)">
3059
3061
  <xsl:message>PTX:ERROR: an @xml:id value "<xsl:value-of select="$the-id"/>" was used to specify a runestone component but no item with that id exists.</xsl:message>
@@ -3068,7 +3070,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
3068
3070
  </xsl:when>
3069
3071
  <xsl:otherwise>
3070
3072
  <xsl:apply-templates select="$target" mode="runestone-id"/>
3071
- <xsl:message>PTX:ERROR: runestone-targets template was called with an invalid @output-field value "<xsl:value-of select="$output-field"/>"</xsl:message>
3073
+ <xsl:message>PTX:BUG: runestone-targets template was called with an invalid @output-field value "<xsl:value-of select="$output-field"/>"</xsl:message>
3072
3074
  </xsl:otherwise>
3073
3075
  </xsl:choose>
3074
3076
  <!-- n - 1 separators, required by receiving Javascript -->
@@ -124,7 +124,7 @@
124
124
  <xsl:value-of select="@tolerance" />
125
125
  </xsl:when>
126
126
  <xsl:otherwise>
127
- <xsl:message>PTX:WARNING: '<xsl:value-of select="@doctest" /> tolerance' Sage doctest needs 'tolerance=' attribute</xsl:message>
127
+ <xsl:message>PTX:ERROR: '<xsl:value-of select="@doctest" /> tolerance' Sage doctest needs 'tolerance=' attribute</xsl:message>
128
128
  </xsl:otherwise>
129
129
  </xsl:choose>
130
130
  </xsl:when>
@@ -137,7 +137,7 @@
137
137
  <xsl:value-of select="@package" />
138
138
  </xsl:when>
139
139
  <xsl:otherwise>
140
- <xsl:message>PTX:WARNING: 'optional' Sage doctest missing package, supply a 'package=' attribute</xsl:message>
140
+ <xsl:message>PTX:ERROR: 'optional' Sage doctest missing package, supply a 'package=' attribute</xsl:message>
141
141
  </xsl:otherwise>
142
142
  </xsl:choose>
143
143
  </xsl:when>
@@ -932,6 +932,31 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
932
932
  </xsl:choose>
933
933
  </xsl:template>
934
934
 
935
+ <!-- Collapse each newline, and the horizontal space around -->
936
+ <!-- it, to a single space: hard-wrapped, indented source -->
937
+ <!-- becomes one long line -->
938
+ <xsl:template name="flatten-line-breaks">
939
+ <xsl:param name="text"/>
940
+ <xsl:choose>
941
+ <xsl:when test="contains($text, '&#xa;')">
942
+ <xsl:call-template name="strip-trailing-whitespace">
943
+ <xsl:with-param name="text" select="substring-before($text, '&#xa;')"/>
944
+ </xsl:call-template>
945
+ <xsl:text> </xsl:text>
946
+ <xsl:call-template name="flatten-line-breaks">
947
+ <xsl:with-param name="text">
948
+ <xsl:call-template name="strip-leading-whitespace">
949
+ <xsl:with-param name="text" select="substring-after($text, '&#xa;')"/>
950
+ </xsl:call-template>
951
+ </xsl:with-param>
952
+ </xsl:call-template>
953
+ </xsl:when>
954
+ <xsl:otherwise>
955
+ <xsl:value-of select="$text"/>
956
+ </xsl:otherwise>
957
+ </xsl:choose>
958
+ </xsl:template>
959
+
935
960
  <!-- spurious newlines introduce whitespace on either side -->
936
961
  <!-- we split at newlines, strip consecutive whitesapce on either side, -->
937
962
  <!-- and replace newlines by spaces (could restore a single newline) -->
@@ -1010,6 +1035,49 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1010
1035
  <xsl:value-of select="str:replace($text, $json-replacements-search-set, $json-replacements-replace-set)" />
1011
1036
  </xsl:template>
1012
1037
 
1038
+ <!-- REGEX Escaped Strings -->
1039
+ <!-- When a string will be passed for comparison using regexp -->
1040
+ <!-- but we want a literal match, we need to escape all of the -->
1041
+ <!-- special characters by putting a slash in front. -->
1042
+ <xsl:variable name="regexp-replacements">
1043
+ <search>\</search>
1044
+ <replace>\\</replace>
1045
+ <search>.</search>
1046
+ <replace>\.</replace>
1047
+ <search>^</search>
1048
+ <replace>\^</replace>
1049
+ <search>$</search>
1050
+ <replace>\$</replace>
1051
+ <search>*</search>
1052
+ <replace>\*</replace>
1053
+ <search>+</search>
1054
+ <replace>\+</replace>
1055
+ <search>?</search>
1056
+ <replace>\?</replace>
1057
+ <search>{</search>
1058
+ <replace>\{</replace>
1059
+ <search>}</search>
1060
+ <replace>\}</replace>
1061
+ <search>[</search>
1062
+ <replace>\[</replace>
1063
+ <search>]</search>
1064
+ <replace>\]</replace>
1065
+ <search>(</search>
1066
+ <replace>\(</replace>
1067
+ <search>)</search>
1068
+ <replace>\)</replace>
1069
+ <search>|</search>
1070
+ <replace>\|</replace>
1071
+ </xsl:variable>
1072
+ <xsl:variable name="regexp-replacements-search-set" select="exsl:node-set($regexp-replacements)/search" />
1073
+ <xsl:variable name="regexp-replacements-replace-set" select="exsl:node-set($regexp-replacements)/replace" />
1074
+
1075
+ <xsl:template name="escape-regexp-literal">
1076
+ <xsl:param name="text"/>
1077
+
1078
+ <xsl:value-of select="str:replace($text, $regexp-replacements-search-set, $regexp-replacements-replace-set)" />
1079
+ </xsl:template>
1080
+
1013
1081
  <xsl:template name="quote-string">
1014
1082
  <xsl:param name="text" />
1015
1083
  <xsl:text>"</xsl:text>
@@ -1093,7 +1161,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1093
1161
  <xsl:when test="$characters = ''">
1094
1162
  <xsl:message>PTX:FATAL: Unable to find an unused character in:&#xa;<xsl:value-of select="$string" />&#xa;using characters from: <xsl:value-of select="$charset" /></xsl:message>
1095
1163
  <xsl:apply-templates select="." mode="location-report" />
1096
- <xsl:message terminate="yes"> That's fatal. Sorry. Quitting...</xsl:message>
1164
+ <xsl:message terminate="yes">PTX:FATAL: Quitting...</xsl:message>
1097
1165
  </xsl:when>
1098
1166
  <xsl:otherwise>
1099
1167
  <xsl:value-of select="substring($characters, 1, 1)"/>