@pretextbook/pretext-html 0.16.0 → 0.17.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 (60) hide show
  1. package/README.md +77 -3
  2. package/assets/preview-html.xsl +56 -0
  3. package/assets/upstream.json +2 -2
  4. package/assets/xsl/entities.ent +14 -1
  5. package/assets/xsl/latex/pretext-latex-texstyle.xsl +5 -2
  6. package/assets/xsl/localizations/README.md +1 -1
  7. package/assets/xsl/localizations/af-ZA.xml +5 -6
  8. package/assets/xsl/localizations/bg-BG.xml +5 -6
  9. package/assets/xsl/localizations/ca-ES.xml +5 -6
  10. package/assets/xsl/localizations/cs-CZ.xml +5 -6
  11. package/assets/xsl/localizations/de-DE.xml +108 -108
  12. package/assets/xsl/localizations/en-US.xml +18 -17
  13. package/assets/xsl/localizations/es-ES.xml +5 -6
  14. package/assets/xsl/localizations/fi-FI.xml +5 -6
  15. package/assets/xsl/localizations/fr-CA.xml +5 -6
  16. package/assets/xsl/localizations/fr-FR.xml +5 -6
  17. package/assets/xsl/localizations/hu-HU.xml +5 -6
  18. package/assets/xsl/localizations/it-IT.xml +7 -7
  19. package/assets/xsl/localizations/ku-CKB.xml +5 -6
  20. package/assets/xsl/localizations/nl-NL.xml +5 -6
  21. package/assets/xsl/localizations/pt-BR.xml +4 -5
  22. package/assets/xsl/localizations/pt-PT.xml +4 -5
  23. package/assets/xsl/localizations/zh-HANS.xml +5 -6
  24. package/assets/xsl/pretext-assembly.xsl +154 -29
  25. package/assets/xsl/pretext-beamer.xsl +112 -10
  26. package/assets/xsl/pretext-braille-preprint.xsl +22 -3
  27. package/assets/xsl/pretext-common.xsl +117 -42
  28. package/assets/xsl/pretext-epub.xsl +74 -87
  29. package/assets/xsl/pretext-fo.xsl +115 -41
  30. package/assets/xsl/pretext-html.xsl +333 -102
  31. package/assets/xsl/pretext-latex-classic.xsl +48 -35
  32. package/assets/xsl/pretext-latex-common.xsl +160 -98
  33. package/assets/xsl/pretext-latex.xsl +12 -10
  34. package/assets/xsl/pretext-markdown.xsl +5 -3
  35. package/assets/xsl/pretext-numbers.xsl +28 -2
  36. package/assets/xsl/pretext-revealjs.xsl +44 -2
  37. package/assets/xsl/pretext-runestone-static.xsl +27 -4
  38. package/assets/xsl/pretext-runestone.xsl +112 -0
  39. package/assets/xsl/pretext-text.xsl +21 -14
  40. package/assets/xsl/publisher-variables.xsl +187 -47
  41. package/assets/xsl/support/extract-math.xsl +22 -2
  42. package/assets/xsl/support/package-math.xsl +9 -8
  43. package/assets/xsl/utilities/report-publisher-variables.xsl +4 -0
  44. package/assets/xsl-bundle.json +1 -1
  45. package/dist/cli-C0JwLhuv.js +1456 -0
  46. package/dist/cli.js +3 -3
  47. package/dist/html-static.d.ts +2 -2
  48. package/dist/index.browser.d.ts +9 -4
  49. package/dist/index.browser.js +1151 -841
  50. package/dist/index.d.ts +9 -3
  51. package/dist/index.js +50 -46
  52. package/dist/publication.d.ts +21 -0
  53. package/dist/renderer.d.ts +134 -13
  54. package/dist/skeleton.d.ts +68 -7
  55. package/dist/source-cache.d.ts +36 -0
  56. package/dist/sourcemap.d.ts +11 -1
  57. package/dist/subtree.d.ts +79 -0
  58. package/dist/xinclude.d.ts +40 -3
  59. package/package.json +1 -1
  60. package/dist/cli-ox-z2TCZ.js +0 -1145
@@ -90,6 +90,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
90
90
  <xsl:call-template name="valign-letter">
91
91
  <xsl:with-param name="valign" select="$slides-valign-default"/>
92
92
  </xsl:call-template>
93
+ <xsl:call-template name="beamer-not-a-slide"/>
93
94
  <xsl:text>]&#xa;</xsl:text>
94
95
  <xsl:text>\frametitle{</xsl:text>
95
96
  <xsl:apply-templates select="." mode="type-name">
@@ -156,6 +157,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
156
157
  <xsl:call-template name="valign-letter">
157
158
  <xsl:with-param name="valign" select="$slides-valign-default"/>
158
159
  </xsl:call-template>
160
+ <xsl:call-template name="beamer-not-a-slide"/>
159
161
  <xsl:text>]&#xa;</xsl:text>
160
162
  <xsl:text>\titlepage&#xa;</xsl:text>
161
163
  <xsl:text>\end{frame}&#xa;&#xa;</xsl:text>
@@ -167,6 +169,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
167
169
  <xsl:call-template name="valign-letter">
168
170
  <xsl:with-param name="valign" select="$slides-valign-default"/>
169
171
  </xsl:call-template>
172
+ <xsl:call-template name="beamer-not-a-slide"/>
170
173
  <xsl:text>]&#xa;</xsl:text>
171
174
  <xsl:text>\frametitle{</xsl:text>
172
175
  <xsl:apply-templates select="." mode="type-name"/>
@@ -197,6 +200,16 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
197
200
  </xsl:choose>
198
201
  </xsl:template>
199
202
 
203
+ <!-- With PreTeXt's slide numbers, a frame that is not a "slide" -->
204
+ <!-- (title, contents, abstract, section title) does not advance -->
205
+ <!-- Beamer's count of frames, so that count, and the total a theme -->
206
+ <!-- may show or use for a progress bar, is a count of slides. -->
207
+ <xsl:template name="beamer-not-a-slide">
208
+ <xsl:if test="$b-beamer-slide-numbering">
209
+ <xsl:text>,noframenumbering</xsl:text>
210
+ </xsl:if>
211
+ </xsl:template>
212
+
200
213
  <!-- A "section" is a Beamer section (navigation, table of contents) -->
201
214
  <!-- with a section-title frame, as in the reveal.js conversion. -->
202
215
  <xsl:template match="slideshow/section">
@@ -207,6 +220,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
207
220
  <xsl:call-template name="valign-letter">
208
221
  <xsl:with-param name="valign" select="$slides-valign-default"/>
209
222
  </xsl:call-template>
223
+ <xsl:call-template name="beamer-not-a-slide"/>
210
224
  <xsl:text>]&#xa;</xsl:text>
211
225
  <xsl:text>\sectionpage&#xa;</xsl:text>
212
226
  <xsl:text>\end{frame}&#xa;&#xa;</xsl:text>
@@ -217,6 +231,11 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
217
231
  <!-- realized through the "listings" package (or other verbatim-like -->
218
232
  <!-- material) must be marked "fragile". -->
219
233
  <xsl:template match="slide">
234
+ <xsl:if test="$b-beamer-slide-numbering">
235
+ <xsl:text>\renewcommand{\ptxslidenumber}{</xsl:text>
236
+ <xsl:apply-templates select="." mode="number"/>
237
+ <xsl:text>}\ptxslidetrue&#xa;</xsl:text>
238
+ </xsl:if>
220
239
  <xsl:text>\begin{frame}[</xsl:text>
221
240
  <xsl:call-template name="valign-letter">
222
241
  <xsl:with-param name="valign">
@@ -231,7 +250,11 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
231
250
  <xsl:apply-templates select="." mode="title-full"/>
232
251
  <xsl:text>}&#xa;</xsl:text>
233
252
  <xsl:apply-templates/>
234
- <xsl:text>\end{frame}&#xa;&#xa;</xsl:text>
253
+ <xsl:text>\end{frame}&#xa;</xsl:text>
254
+ <xsl:if test="$b-beamer-slide-numbering">
255
+ <xsl:text>\ptxslidefalse&#xa;</xsl:text>
256
+ </xsl:if>
257
+ <xsl:text>&#xa;</xsl:text>
235
258
  </xsl:template>
236
259
 
237
260
  <!-- A "subslide" is material that appears, as one group, after an -->
@@ -367,8 +390,9 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
367
390
  </xsl:call-template>
368
391
  </xsl:template>
369
392
 
370
- <!-- Everything else theorem-ish, plus remarks and asides, is a -->
371
- <!-- generic Beamer "block" headed by its type-name and title -->
393
+ <!-- Everything else theorem-ish, plus remarks and asides, is a -->
394
+ <!-- generic Beamer "block" headed by its type-name and title, and -->
395
+ <!-- for a mathematical block the parenthesized attribution -->
372
396
  <xsl:template match="&THEOREM-LIKE;|&AXIOM-LIKE;|&REMARK-LIKE;|&COMPUTATION-LIKE;|&ASIDE-LIKE;|&GOAL-LIKE;|assemblage">
373
397
  <xsl:text>\begin{block}{</xsl:text>
374
398
  <xsl:apply-templates select="." mode="type-name"/>
@@ -376,23 +400,40 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
376
400
  <xsl:text>: </xsl:text>
377
401
  <xsl:apply-templates select="." mode="title-full"/>
378
402
  </xsl:if>
403
+ <xsl:if test="creator or origins">
404
+ <xsl:text> (</xsl:text>
405
+ <xsl:apply-templates select="." mode="attribution-full"/>
406
+ <xsl:text>)</xsl:text>
407
+ </xsl:if>
379
408
  <xsl:text>}&#xa;</xsl:text>
380
409
  <xsl:apply-templates select="*[not(&PROOF-FILTER;)]"/>
381
410
  <xsl:text>\end{block}&#xa;</xsl:text>
382
411
  <xsl:apply-templates select="&PROOF-LIKE;"/>
383
412
  </xsl:template>
384
413
 
385
- <!-- The common core: the environment, an optional title in the -->
386
- <!-- optional argument, the guts, and any proof following outside -->
414
+ <!-- The common core: the environment, the optional argument, the -->
415
+ <!-- guts, and any proof following outside. Beamer sets the -->
416
+ <!-- optional argument in parentheses, so a title, the creator, and -->
417
+ <!-- the origins share that one group, separated by commas, as in -->
418
+ <!-- the classic LaTeX conversion. Braces protect the argument: a -->
419
+ <!-- citation such as [3] would otherwise end it at the first "]". -->
387
420
  <xsl:template name="beamer-environment">
388
421
  <xsl:param name="environment"/>
389
422
  <xsl:text>\begin{</xsl:text>
390
423
  <xsl:value-of select="$environment"/>
391
424
  <xsl:text>}</xsl:text>
392
- <xsl:if test="title">
393
- <xsl:text>[</xsl:text>
394
- <xsl:apply-templates select="." mode="title-full"/>
395
- <xsl:text>]</xsl:text>
425
+ <xsl:if test="title or creator or origins">
426
+ <xsl:text>[{</xsl:text>
427
+ <xsl:if test="title">
428
+ <xsl:apply-templates select="." mode="title-xref"/>
429
+ </xsl:if>
430
+ <xsl:if test="title and (creator or origins)">
431
+ <xsl:text>, </xsl:text>
432
+ </xsl:if>
433
+ <xsl:if test="creator or origins">
434
+ <xsl:apply-templates select="." mode="attribution-full"/>
435
+ </xsl:if>
436
+ <xsl:text>}]</xsl:text>
396
437
  </xsl:if>
397
438
  <xsl:text>&#xa;</xsl:text>
398
439
  <xsl:apply-templates select="*[not(&PROOF-FILTER;)]"/>
@@ -477,8 +518,41 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
477
518
  <!-- Beamer-specific treatment of \alert and no styling hooks) and -->
478
519
  <!-- the engine/font setup (fontenc/fontspec, where the regular -->
479
520
  <!-- "font-support" prescribes document fonts a theme should control). -->
521
+
522
+ <!-- The Beamer class names a slide's shape with the digits of the -->
523
+ <!-- aspect ratio run together, so "16:9" becomes "aspectratio=169". -->
524
+ <!-- The publisher expresses the ratio in its readable form, and the -->
525
+ <!-- options the publication file admits are exactly those the class -->
526
+ <!-- recognizes, so no value can reach here without a translation. -->
527
+ <xsl:template name="beamer-aspect-ratio-option">
528
+ <xsl:choose>
529
+ <xsl:when test="$beamer-aspect-ratio = '4:3'">
530
+ <xsl:text>43</xsl:text>
531
+ </xsl:when>
532
+ <xsl:when test="$beamer-aspect-ratio = '16:9'">
533
+ <xsl:text>169</xsl:text>
534
+ </xsl:when>
535
+ <xsl:when test="$beamer-aspect-ratio = '16:10'">
536
+ <xsl:text>1610</xsl:text>
537
+ </xsl:when>
538
+ <xsl:when test="$beamer-aspect-ratio = '14:9'">
539
+ <xsl:text>149</xsl:text>
540
+ </xsl:when>
541
+ <xsl:when test="$beamer-aspect-ratio = '5:4'">
542
+ <xsl:text>54</xsl:text>
543
+ </xsl:when>
544
+ <xsl:when test="$beamer-aspect-ratio = '3:2'">
545
+ <xsl:text>32</xsl:text>
546
+ </xsl:when>
547
+ </xsl:choose>
548
+ </xsl:template>
549
+
480
550
  <xsl:template name="beamer-preamble">
481
- <xsl:text>\documentclass[11pt, compress]{beamer}&#xa;</xsl:text>
551
+ <xsl:text>\documentclass[</xsl:text>
552
+ <xsl:value-of select="$beamer-font-size"/>
553
+ <xsl:text>, aspectratio=</xsl:text>
554
+ <xsl:call-template name="beamer-aspect-ratio-option"/>
555
+ <xsl:text>, compress]{beamer}&#xa;</xsl:text>
482
556
  <xsl:if test="$latex.preamble.early != ''">
483
557
  <xsl:text>%% Custom Preamble Entries, early (use latex.preamble.early)&#xa;</xsl:text>
484
558
  <xsl:value-of select="$latex.preamble.early" />
@@ -500,6 +574,34 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
500
574
  <xsl:text>\usefonttheme[onlymath]{serif}&#xa;</xsl:text>
501
575
  <xsl:text>%% quash navigation symbols&#xa;</xsl:text>
502
576
  <xsl:text>\setbeamertemplate{navigation symbols}{}&#xa;</xsl:text>
577
+ <!-- Every theme that shows a frame number, whether in a template -->
578
+ <!-- or directly, and every progress bar, gets it from the command -->
579
+ <!-- \insertframenumber. So it becomes PreTeXt's number of the -->
580
+ <!-- most recent slide, which is always a number, as a theme doing -->
581
+ <!-- arithmetic with it requires (so 0 before the first slide). -->
582
+ <!-- A theme displays the number through a template: "page number -->
583
+ <!-- in head/foot" for most (some leave it empty, others add a -->
584
+ <!-- total, which would announce how long a talk runs), "frame -->
585
+ <!-- numbering" for metropolis. Both show the number alone, and -->
586
+ <!-- only on a frame that is a slide, as the flag \ifptxslide says. -->
587
+ <!-- Without slide numbers, both templates are empty, so no theme -->
588
+ <!-- shows a number, just as a Reveal.js slideshow shows none. -->
589
+ <xsl:choose>
590
+ <xsl:when test="$b-beamer-slide-numbering">
591
+ <xsl:text>%% PreTeXt's slide numbers, wherever a theme shows a frame number,&#xa;</xsl:text>
592
+ <xsl:text>%% alone, and only on a frame that is a slide&#xa;</xsl:text>
593
+ <xsl:text>\newif\ifptxslide&#xa;</xsl:text>
594
+ <xsl:text>\newcommand{\ptxslidenumber}{0}&#xa;</xsl:text>
595
+ <xsl:text>\renewcommand{\insertframenumber}{\ptxslidenumber}&#xa;</xsl:text>
596
+ <xsl:text>\setbeamertemplate{page number in head/foot}{\ifptxslide\insertframenumber\fi}&#xa;</xsl:text>
597
+ <xsl:text>\setbeamertemplate{frame numbering}{\ifptxslide\insertframenumber\fi}&#xa;</xsl:text>
598
+ </xsl:when>
599
+ <xsl:otherwise>
600
+ <xsl:text>%% no slide numbers, whatever the theme&#xa;</xsl:text>
601
+ <xsl:text>\setbeamertemplate{page number in head/foot}{}&#xa;</xsl:text>
602
+ <xsl:text>\setbeamertemplate{frame numbering}{}&#xa;</xsl:text>
603
+ </xsl:otherwise>
604
+ </xsl:choose>
503
605
  <xsl:text>%% every "section" gets a section-title frame via \sectionpage&#xa;</xsl:text>
504
606
  <xsl:text>&#xa;%%%% Start PreTeXt generated preamble %%%%&#xa;&#xa;</xsl:text>
505
607
  <xsl:text>\usepackage{amsmath}&#xa;</xsl:text>
@@ -156,7 +156,9 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
156
156
  <!-- *are* present in "math-original" but that introduces a new -->
157
157
  <!-- element in-between "md" and "mrow", so matches on -->
158
158
  <!-- "md[mrow]" can be problematic here (and perhaps elsewhere). -->
159
- <xsl:template match="m|md" mode="meld-math">
159
+ <!-- Music notation ("n", "scaledeg", "timesignature", "chord") is -->
160
+ <!-- set as inline math, so it has a representation as an "m" does. -->
161
+ <xsl:template match="m|md|n|scaledeg|timesignature|chord" mode="meld-math">
160
162
  <!-- preserve author's element -->
161
163
  <xsl:copy>
162
164
  <!-- preserve attributes -->
@@ -1779,6 +1781,23 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1779
1781
  </xsl:choose>
1780
1782
  </xsl:template>
1781
1783
 
1784
+ <!-- Music notation ("n", "scaledeg", "timesignature", "chord") is -->
1785
+ <!-- LaTeX built by the -common templates and set as inline math, -->
1786
+ <!-- melded with a Nemeth representation just as an "m" is. It -->
1787
+ <!-- always has structure (an accidental, an octave, a chord's -->
1788
+ <!-- figures), so it is never one of the simple cases above, and it -->
1789
+ <!-- absorbs no clause-ending punctuation, so none is restored here. -->
1790
+ <xsl:template match="n|scaledeg|timesignature|chord">
1791
+ <xsl:variable name="raw-braille">
1792
+ <xsl:call-template name="brf-symbols-filter">
1793
+ <xsl:with-param name="text" select="math-nemeth"/>
1794
+ </xsl:call-template>
1795
+ </xsl:variable>
1796
+ <math>
1797
+ <xsl:value-of select="$raw-braille"/>
1798
+ </math>
1799
+ </xsl:template>
1800
+
1782
1801
  <xsl:template match="m[contains(math-nemeth, '&#xa;')]|md">
1783
1802
  <!-- Lines are trimmed, and possibly converted to BRF ASCII -->
1784
1803
  <!-- symbols ("early"), one at a time, below -->
@@ -2338,7 +2357,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
2338
2357
  <!-- xref: xref-number and xref-link defined above -->
2339
2358
  <!-- today, timeofday: pure text in common -->
2340
2359
  <!-- ad, am, bc, ca, eg, etal, etc, ie, nb, pm, ps, vs, viz: Latin abbreviations, defined as text in common -->
2341
- <!-- title, subtitle, shorttitle, plaintitle, creator: killed in common as metadata -->
2360
+ <!-- title, subtitle, shorttitle, plaintitle, creator, origins: killed in common as metadata -->
2342
2361
  <!-- caption: killed in common as metadata -->
2343
2362
  <!-- cline: a simple template in common is active -->
2344
2363
  <!-- c: a simple template in common is active -->
@@ -2433,7 +2452,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
2433
2452
  self::xref or
2434
2453
  self::today or self::timeofday or
2435
2454
  self::ad or self::am or self::bc or self::ca or self::eg or self::etal or self::etc or self::ie or self::nb or self::pm or self::ps or self::vs or self::viz or
2436
- self::title or self::subtitle or self::shorttitle or self::plaintitle or self::creator or
2455
+ self::title or self::subtitle or self::shorttitle or self::plaintitle or self::creator or self::origins or
2437
2456
  self::caption or
2438
2457
  self::cline or
2439
2458
  self::c or
@@ -2230,8 +2230,9 @@ Book (with parts), "section" at level 3
2230
2230
  <!-- of its own, since there is no enclosing "figure" -->
2231
2231
  <!-- -->
2232
2232
  <!-- "subnumber" - a panel of a side-by-side, which in turn is a -->
2233
- <!-- child/descendant of a "figure" (a "sbsgroup" may intervene). -->
2234
- <!-- This triggers a block number foor the exterior "figure" and -->
2233
+ <!-- child/descendant of a "figure" (a "sbsgroup" may intervene), -->
2234
+ <!-- or a "figure" in a "stack" that is the content of a "figure". -->
2235
+ <!-- This triggers a block number for the exterior "figure" and -->
2235
2236
  <!-- a subnumber for the interior FIGURE-LIKE. -->
2236
2237
  <!-- -->
2237
2238
  <!-- (These code comments are referenced in the LaTeX conversion.) -->
@@ -2242,6 +2243,9 @@ Book (with parts), "section" at level 3
2242
2243
  <xsl:when test="parent::sidebyside and ancestor::figure">
2243
2244
  <xsl:text>subnumber</xsl:text>
2244
2245
  </xsl:when>
2246
+ <xsl:when test="self::figure and parent::stack/parent::figure">
2247
+ <xsl:text>subnumber</xsl:text>
2248
+ </xsl:when>
2245
2249
  <xsl:when test="parent::sidebyside">
2246
2250
  <xsl:text>panel</xsl:text>
2247
2251
  </xsl:when>
@@ -2522,16 +2526,17 @@ Book (with parts), "section" at level 3
2522
2526
  <!-- the localization routines. -->
2523
2527
 
2524
2528
 
2525
- <!-- With modal templates below, the default template does nothing -->
2526
- <!-- We include the "creator" element of a theorem/axiom as metadata -->
2527
- <!-- NB: since these elements get killed on-sight, when we actually -->
2528
- <!-- want to process them we need to use a "select" attribute -->
2529
- <!-- similar to title/*|title/text() or title/node(). -->
2529
+ <!-- With modal templates below, the default template does nothing -->
2530
+ <!-- The "creator" and "origins" of a mathematical block are metadata -->
2531
+ <!-- NB: since these elements get killed on-sight, when we actually -->
2532
+ <!-- want to process them we need to use a "select" attribute -->
2533
+ <!-- similar to title/*|title/text() or title/node(). -->
2530
2534
  <xsl:template match="title" />
2531
2535
  <xsl:template match="subtitle" />
2532
2536
  <xsl:template match="shorttitle"/>
2533
2537
  <xsl:template match="plaintitle"/>
2534
2538
  <xsl:template match="creator" />
2539
+ <xsl:template match="origins"/>
2535
2540
 
2536
2541
  <!-- Some items have default titles that make sense -->
2537
2542
  <!-- Typically these are one-off subdivisions (eg preface), -->
@@ -2742,6 +2747,10 @@ Book (with parts), "section" at level 3
2742
2747
  <xsl:when test="plaintitle">
2743
2748
  <xsl:apply-templates select="plaintitle/text()"/>
2744
2749
  </xsl:when>
2750
+ <!-- only the lines, not the whitespace between them -->
2751
+ <xsl:when test="title/line">
2752
+ <xsl:apply-templates select="title/line" mode="plain-title-edit"/>
2753
+ </xsl:when>
2745
2754
  <xsl:when test="title">
2746
2755
  <xsl:apply-templates select="title/node()[not(self::fn)]" mode="plain-title-edit"/>
2747
2756
  </xsl:when>
@@ -2756,8 +2765,24 @@ Book (with parts), "section" at level 3
2756
2765
 
2757
2766
  <!-- Plain subtitle: used for HTML <meta> tags -->
2758
2767
  <xsl:template match="*" mode="subtitle-plain">
2759
- <xsl:if test="subtitle">
2760
- <xsl:apply-templates select="subtitle/node()[not(self::fn)]" mode="plain-title-edit"/>
2768
+ <xsl:choose>
2769
+ <!-- only the lines, not the whitespace between them -->
2770
+ <xsl:when test="subtitle/line">
2771
+ <xsl:apply-templates select="subtitle/line" mode="plain-title-edit"/>
2772
+ </xsl:when>
2773
+ <xsl:when test="subtitle">
2774
+ <xsl:apply-templates select="subtitle/node()[not(self::fn)]" mode="plain-title-edit"/>
2775
+ </xsl:when>
2776
+ </xsl:choose>
2777
+ </xsl:template>
2778
+
2779
+ <!-- The lines of a structured title (or subtitle) run together -->
2780
+ <!-- in a plain version, separated by a space, as they are in -->
2781
+ <!-- the "title-simple" template -->
2782
+ <xsl:template match="title/line|subtitle/line" mode="plain-title-edit">
2783
+ <xsl:apply-templates select="node()[not(self::fn)]" mode="plain-title-edit"/>
2784
+ <xsl:if test="following-sibling::line">
2785
+ <xsl:text> </xsl:text>
2761
2786
  </xsl:if>
2762
2787
  </xsl:template>
2763
2788
 
@@ -2822,7 +2847,7 @@ Book (with parts), "section" at level 3
2822
2847
  <!-- pieces simply so it is more readable. -->
2823
2848
  <!-- -->
2824
2849
  <!-- Blocks -->
2825
- <xsl:template match="&THEOREM-LIKE;|&PROOF-LIKE;|&AXIOM-LIKE;|&DEFINITION-LIKE;|&REMARK-LIKE;|&COMPUTATION-LIKE;|&EXAMPLE-LIKE;|&PROJECT-LIKE;|&ASIDE-LIKE;|exercise|assemblage" mode="title-wants-punctuation">
2850
+ <xsl:template match="&THEOREM-LIKE;|&PROOF-LIKE;|&AXIOM-LIKE;|&DEFINITION-LIKE;|&REMARK-LIKE;|&COMPUTATION-LIKE;|&OPENPROBLEM-LIKE;|&EXAMPLE-LIKE;|&PROJECT-LIKE;|&ASIDE-LIKE;|exercise|assemblage" mode="title-wants-punctuation">
2826
2851
  <xsl:value-of select="true()"/>
2827
2852
  </xsl:template>
2828
2853
  <!-- Miscellaneous -->
@@ -2841,11 +2866,36 @@ Book (with parts), "section" at level 3
2841
2866
  <xsl:value-of select="false()"/>
2842
2867
  </xsl:template>
2843
2868
 
2844
- <xsl:template match="&THEOREM-LIKE;|&AXIOM-LIKE;" mode="creator-full">
2869
+ <!-- The attribution of a mathematical block: the "creator" (a name, -->
2870
+ <!-- as short text) and the "origins" (cross-references, typically to -->
2871
+ <!-- bibliography entries). Each conversion places the whole group -->
2872
+ <!-- after the title, in parentheses, so the pieces here carry only -->
2873
+ <!-- the commas between them. -->
2874
+ <xsl:template match="&THEOREM-LIKE;|&AXIOM-LIKE;|&DEFINITION-LIKE;|&OPENPROBLEM-LIKE;" mode="creator-full">
2845
2875
  <!-- select="creator" would just get it killed -->
2846
2876
  <xsl:apply-templates select="creator/*|creator/text()" />
2847
2877
  </xsl:template>
2848
2878
 
2879
+ <!-- The schema allows only "xref" inside "origins", so each one is -->
2880
+ <!-- a live cross-reference; commas separate them, with no -->
2881
+ <!-- conjunction before the last -->
2882
+ <xsl:template match="&THEOREM-LIKE;|&AXIOM-LIKE;|&DEFINITION-LIKE;|&OPENPROBLEM-LIKE;" mode="origins-full">
2883
+ <xsl:for-each select="origins/xref">
2884
+ <xsl:if test="preceding-sibling::xref">
2885
+ <xsl:text>, </xsl:text>
2886
+ </xsl:if>
2887
+ <xsl:apply-templates select="."/>
2888
+ </xsl:for-each>
2889
+ </xsl:template>
2890
+
2891
+ <xsl:template match="&THEOREM-LIKE;|&AXIOM-LIKE;|&DEFINITION-LIKE;|&OPENPROBLEM-LIKE;" mode="attribution-full">
2892
+ <xsl:apply-templates select="." mode="creator-full"/>
2893
+ <xsl:if test="creator and origins">
2894
+ <xsl:text>, </xsl:text>
2895
+ </xsl:if>
2896
+ <xsl:apply-templates select="." mode="origins-full"/>
2897
+ </xsl:template>
2898
+
2849
2899
  <!-- Structured titles -->
2850
2900
 
2851
2901
  <!-- Each "line", except the last, gets a separator -->
@@ -2904,13 +2954,17 @@ Book (with parts), "section" at level 3
2904
2954
  <!-- -->
2905
2955
  <!-- 1. in a figure (itself not in a sidebyside) where it -->
2906
2956
  <!-- can have a width specification on itself -->
2907
- <!-- 2. in a sidebyside directly, or a figure in a sidebyside. -->
2957
+ <!-- 2. as a panel of a sidebyside, or in a figure that is a panel. -->
2908
2958
  <!-- These widths come from the layout, and are converter dependent -->
2959
+ <!-- 3. more deeply within a sidebyside, such as in an "exercise" -->
2960
+ <!-- panel or in a list item. The layout does not size it, so it -->
2961
+ <!-- is handled as in case 1, relative to the available width -->
2962
+ <!-- where it sits. -->
2909
2963
  <!-- -->
2910
- <!-- Entirely similar for jsxgraph, audio and video but we do -->
2911
- <!-- not consult default *image* width in docinfo -->
2964
+ <!-- Entirely similar for jsxgraph, audio, video, interactive and slate, -->
2965
+ <!-- but we do not consult default *image* width in docinfo -->
2912
2966
 
2913
- <xsl:template match="image[not(ancestor::sidebyside)]|audio[not(ancestor::sidebyside)]|video[not(ancestor::sidebyside)]|jsxgraph[not(ancestor::sidebyside)]|interactive[not(ancestor::sidebyside)]|slate[not(ancestor::sidebyside)]" mode="get-width-percentage">
2967
+ <xsl:template match="image[not(&SBS-LAYOUT-FILTER;)]|audio[not(&SBS-LAYOUT-FILTER;)]|video[not(&SBS-LAYOUT-FILTER;)]|jsxgraph[not(&SBS-LAYOUT-FILTER;)]|interactive[not(&SBS-LAYOUT-FILTER;)]|slate[not(&SBS-LAYOUT-FILTER;)]" mode="get-width-percentage">
2914
2968
  <!-- find it first -->
2915
2969
  <xsl:variable name="raw-width">
2916
2970
  <xsl:choose>
@@ -2948,11 +3002,13 @@ Book (with parts), "section" at level 3
2948
3002
  </xsl:choose>
2949
3003
  </xsl:template>
2950
3004
 
2951
- <!-- Any way that an image gets placed in a sidebyside -->
2952
- <!-- panel it should have a relative size filling that -->
2953
- <!-- panel, so this is easy, just 100% all the time -->
2954
- <!-- Exception: asymptote WebGL needs actual pixels -->
2955
- <xsl:template match="image[ancestor::sidebyside]" mode="get-width-percentage">
3005
+ <!-- An image that is a panel of a sidebyside, or that is -->
3006
+ <!-- the content of a figure panel, has a relative size -->
3007
+ <!-- filling that panel, so this is easy, just 100% all the -->
3008
+ <!-- time. An image more deeply within a sidebyside is -->
3009
+ <!-- handled above. -->
3010
+ <!-- Exception: asymptote WebGL needs actual pixels -->
3011
+ <xsl:template match="image[&SBS-LAYOUT-FILTER;]" mode="get-width-percentage">
2956
3012
  <xsl:text>100%</xsl:text>
2957
3013
  </xsl:template>
2958
3014
 
@@ -2968,8 +3024,8 @@ Book (with parts), "section" at level 3
2968
3024
  <!-- of the sidebyside, a naked object, or a figure holding the object -->
2969
3025
  <!-- Widths from sidebyside layouts have been error-checked as input -->
2970
3026
 
2971
- <!-- occurs in a figure, not contained in a sidebyside -->
2972
- <xsl:template match="audio[ancestor::sidebyside]|video[ancestor::sidebyside]|jsxgraph[ancestor::sidebyside]|interactive[ancestor::sidebyside]|slate[ancestor::sidebyside]|image[asymptote and ancestor::sidebyside]|image[sageplot and ancestor::sidebyside]" mode="get-width-percentage">
3027
+ <!-- a panel of a sidebyside, or the content of a stack or figure panel -->
3028
+ <xsl:template match="audio[&SBS-LAYOUT-FILTER;]|video[&SBS-LAYOUT-FILTER;]|jsxgraph[&SBS-LAYOUT-FILTER;]|interactive[&SBS-LAYOUT-FILTER;]|slate[&SBS-LAYOUT-FILTER;]|image[asymptote and (&SBS-LAYOUT-FILTER;)]|image[sageplot and (&SBS-LAYOUT-FILTER;)]" mode="get-width-percentage">
2973
3029
  <!-- in a side-by-side, get layout, locate in layout -->
2974
3030
  <!-- and get width. The layout-parameters template -->
2975
3031
  <!-- will analyze an enclosing sbsgroup -->
@@ -3257,26 +3313,27 @@ Book (with parts), "section" at level 3
3257
3313
  <!-- First, a "divisional" "exercise" in an "exercises", -->
3258
3314
  <!-- with perhaps intervening groups, like an "exercisegroup" -->
3259
3315
  <xsl:template match="exercises//exercise" mode="string-id">
3260
- <xsl:text>divisionalexercise</xsl:text>
3316
+ <xsl:text>exercise-divisional</xsl:text>
3261
3317
  </xsl:template>
3262
3318
 
3263
3319
  <!-- Second, an "exercise" placed within a "worksheet"-->
3264
3320
  <xsl:template match="worksheet//exercise" mode="string-id">
3265
- <xsl:text>worksheetexercise</xsl:text>
3321
+ <xsl:text>exercise-worksheet</xsl:text>
3266
3322
  </xsl:template>
3267
3323
 
3268
3324
  <!-- Third, an "exercise" placed within a "reading-questions"-->
3269
3325
  <xsl:template match="reading-questions//exercise" mode="string-id">
3270
- <xsl:text>readingquestion</xsl:text>
3326
+ <xsl:text>exercise-reading</xsl:text>
3271
3327
  </xsl:template>
3272
3328
 
3273
3329
  <!-- Finally, an inline exercise has a division (several possible) -->
3274
3330
  <!-- as a parent. We just drop in here last if other matches do not -->
3275
3331
  <!-- succeed, but could improve with a filter or list of specific matches -->
3276
- <!-- This matches the LaTeX environment of the same name, so -->
3277
- <!-- template to create an "inlineexercise" environment runs smoothly -->
3332
+ <!-- The LaTeX conversions name their environment for an inline exercise -->
3333
+ <!-- "inlineexercise", written there as a literal: an environment name is -->
3334
+ <!-- not a string-id, and a hyphen does not belong in one. -->
3278
3335
  <xsl:template match="exercise" mode="string-id">
3279
- <xsl:text>inlineexercise</xsl:text>
3336
+ <xsl:text>exercise-inline</xsl:text>
3280
3337
  </xsl:template>
3281
3338
 
3282
3339
  <!-- "solutions" divisions are "Solutions 5.6" in the -->
@@ -4222,7 +4279,7 @@ Book (with parts), "section" at level 3
4222
4279
  </xsl:when>
4223
4280
  <!-- not placed on image, or figure/image, -->
4224
4281
  <!-- but a document-wide default margins exists -->
4225
- <xsl:when test="self::image and not(ancestor::sidebyside) and $docinfo/defaults/images/@margins">
4282
+ <xsl:when test="self::image and not(&SBS-LAYOUT-FILTER;) and $docinfo/defaults/images/@margins">
4226
4283
  <xsl:value-of select="normalize-space($docinfo/defaults/images/@margins)" />
4227
4284
  </xsl:when>
4228
4285
  <!-- default if not specified -->
@@ -4263,7 +4320,7 @@ Book (with parts), "section" at level 3
4263
4320
  </xsl:when>
4264
4321
  <!-- not placed on image, or figure/image, -->
4265
4322
  <!-- but a document-wide default width exists -->
4266
- <xsl:when test="self::image and not(ancestor::sidebyside) and $docinfo/defaults/images/@width">
4323
+ <xsl:when test="self::image and not(&SBS-LAYOUT-FILTER;) and $docinfo/defaults/images/@width">
4267
4324
  <xsl:value-of select="$docinfo/defaults/images/@width" />
4268
4325
  </xsl:when>
4269
4326
  <!-- default setting if not specified, and not global -->
@@ -7140,19 +7197,22 @@ Book (with parts), "section" at level 3
7140
7197
  <!-- categorized by their ancestors. So we recognize certain strings -->
7141
7198
  <!-- as "pseudo-elements". We do this once and then pass them along. -->
7142
7199
  <!-- -->
7143
- <!-- * inlineexercise -->
7144
- <!-- * divisionexercise -->
7145
- <!-- * worksheetexercise -->
7146
- <!-- * readingquestion -->
7200
+ <!-- * exercise-inline -->
7201
+ <!-- * exercise-divisional -->
7202
+ <!-- * exercise-worksheet -->
7203
+ <!-- * exercise-reading -->
7147
7204
  <!-- -->
7148
- <!-- Equality of strings (e.g. 'inlineexercise') and the node-set ($elements)-->
7149
- <!-- is true when the *string-value* of *one* node in the set is identical -->
7150
- <!-- NB: if this gets out-of-hand, it should be passed as a structure -->
7151
- <xsl:variable name="b-inline-exercises" select="'inlineexercise' = $elements"/>
7152
- <xsl:variable name="b-division-exercises" select="'divisionexercise' = $elements"/>
7153
- <xsl:variable name="b-worksheet-exercises" select="'worksheetexercise' = $elements"/>
7154
- <xsl:variable name="b-reading-questions" select="'readingquestion' = $elements"/>
7155
- <!-- display subdivision headings with empty contents? -->
7205
+ <!-- These are the names a publication file uses, and the names an -->
7206
+ <!-- author writes in a "rename", so a type of "exercise" has one name. -->
7207
+ <!-- -->
7208
+ <!-- Equality of strings (e.g. 'exercise-inline') and the node-set -->
7209
+ <!-- ($elements) is true when the *string-value* of *one* node in the -->
7210
+ <!-- set is identical. NB: if this gets out-of-hand, pass a structure -->
7211
+ <xsl:variable name="b-inline-exercises" select="'exercise-inline' = $elements"/>
7212
+ <xsl:variable name="b-division-exercises" select="'exercise-divisional' = $elements"/>
7213
+ <xsl:variable name="b-worksheet-exercises" select="'exercise-worksheet' = $elements"/>
7214
+ <xsl:variable name="b-reading-questions" select="'exercise-reading' = $elements"/>
7215
+ <!-- display subdivision headings with empty contents? -->
7156
7216
  <xsl:variable name="entered-empty">
7157
7217
  <xsl:choose>
7158
7218
  <xsl:when test="not(@empty)">
@@ -11975,6 +12035,21 @@ http://andrewmccarthy.ie/2014/11/06/swung-dash-in-latex/
11975
12035
  <xsl:with-param name="message" select="'an &quot;sbsgroup&quot; now requires at least two &quot;sidebyside&quot;. A group of one behaves exactly like the &quot;sidebyside&quot; alone, so use the &quot;sidebyside&quot; by itself, with the layout attributes moved onto it'"/>
11976
12036
  </xsl:call-template>
11977
12037
  <!-- -->
12038
+ <!-- 2026-09-22 a type of "exercise" is named as in a publication file -->
12039
+ <xsl:call-template name="deprecation-message">
12040
+ <xsl:with-param name="occurrences" select="&quot;$docinfo/rename[(@element = 'inlineexercise') or (@element = 'divisionalexercise') or (@element = 'worksheetexercise') or (@element = 'readingquestion')]&quot;" />
12041
+ <xsl:with-param name="date-string" select="'2026-09-22'" />
12042
+ <xsl:with-param name="message" select="'a &quot;rename&quot; now names a type of &quot;exercise&quot; the way a publication file does: &quot;exercise-inline&quot;, &quot;exercise-divisional&quot;, &quot;exercise-worksheet&quot;, or &quot;exercise-reading&quot;. The one-word names are deprecated, and will continue to be honored'"/>
12043
+ </xsl:call-template>
12044
+ <!-- -->
12045
+ <!-- 2026-09-22 a type of "exercise" is named as in a publication file -->
12046
+ <xsl:call-template name="deprecation-message">
12047
+ <xsl:with-param name="occurrences" select="&quot;$document-root//list-of[contains(@elements, 'inlineexercise') or contains(@elements, 'divisionexercise') or contains(@elements, 'divisionalexercise') or contains(@elements, 'worksheetexercise') or contains(@elements, 'readingquestion')]&quot;" />
12048
+ <xsl:with-param name="date-string" select="'2026-09-22'" />
12049
+ <xsl:with-param name="message" select="'the &quot;elements&quot; attribute of a &quot;list-of&quot; now names a type of &quot;exercise&quot; the way a publication file does: &quot;exercise-inline&quot;, &quot;exercise-divisional&quot;, &quot;exercise-worksheet&quot;, or &quot;exercise-reading&quot;. The one-word names are deprecated, and will continue to be honored'"/>
12050
+ </xsl:call-template>
12051
+ <!-- -->
12052
+ <!-- End of the chronological sequence: a new entry goes just above. -->
11978
12053
  </xsl:template>
11979
12054
 
11980
12055
  <!-- Miscellaneous -->