@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
@@ -142,6 +142,21 @@
142
142
  <!-- but a a boolean sure helps -->
143
143
  <xsl:variable name="b-kindle" select="$math.format = 'kindle'"/>
144
144
 
145
+ <!-- A file holding mathematics must say so in the "properties" of -->
146
+ <!-- its manifest "item", and which property depends only on the -->
147
+ <!-- format of the mathematics. Mathematics as speech is text, so -->
148
+ <!-- it has no property, and the value is empty. -->
149
+ <xsl:variable name="manifest-math-property">
150
+ <xsl:choose>
151
+ <xsl:when test="$math.format = 'mml' or $math.format = 'kindle'">
152
+ <xsl:text>mathml</xsl:text>
153
+ </xsl:when>
154
+ <xsl:when test="$math.format = 'svg'">
155
+ <xsl:text>svg</xsl:text>
156
+ </xsl:when>
157
+ </xsl:choose>
158
+ </xsl:variable>
159
+
145
160
  <!-- If there are footnotes, we'll build and package a "endnotes.xhtml" file -->
146
161
  <xsl:variable name="b-has-endnotes" select="boolean($document-root//fn|$document-root//aside|$document-root//biographical|$document-root//historical)"/>
147
162
 
@@ -394,10 +409,12 @@
394
409
  <xsl:apply-templates select="personname"/>
395
410
  </xsl:element>
396
411
  </xsl:for-each>
397
- <!-- Required in EPUB 3.0.1 spec -->
398
- <!-- TODO: title-types can refine this -->
412
+ <!-- Required in EPUB 3.0.1 spec -->
413
+ <!-- TODO: title-types can refine this -->
414
+ <!-- Text only, so any mathematics is its LaTeX source -->
415
+ <!-- (or the author supplies a "plaintitle" instead) -->
399
416
  <xsl:element name="dc:title">
400
- <xsl:apply-templates select="$document-root" mode="title-full" />
417
+ <xsl:apply-templates select="$document-root" mode="title-plain"/>
401
418
  </xsl:element>
402
419
  <!-- Required in EPUB 3.0.1 spec -->
403
420
  <!-- Repeatable and more complicated, see spec -->
@@ -454,7 +471,20 @@
454
471
  <item id="css-epub" href="{$css-dir}/epub.css" media-type="text/css"/>
455
472
  </xsl:otherwise>
456
473
  </xsl:choose>
457
- <item id="cover-page" href="{$xhtml-dir}/cover-page.xhtml" media-type="application/xhtml+xml"/>
474
+ <!-- Absent an authored image, the cover page shows the -->
475
+ <!-- document's title, which may hold mathematics -->
476
+ <item id="cover-page" href="{$xhtml-dir}/cover-page.xhtml" media-type="application/xhtml+xml">
477
+ <xsl:variable name="has-math">
478
+ <xsl:call-template name="file-has-math">
479
+ <xsl:with-param name="filename" select="'cover-page.xhtml'"/>
480
+ </xsl:call-template>
481
+ </xsl:variable>
482
+ <xsl:if test="$has-math = 'true'">
483
+ <xsl:attribute name="properties">
484
+ <xsl:value-of select="$manifest-math-property"/>
485
+ </xsl:attribute>
486
+ </xsl:if>
487
+ </item>
458
488
  <item id="table-contents"
459
489
  href="{$xhtml-dir}/table-contents.xhtml"
460
490
  media-type="application/xhtml+xml">
@@ -462,27 +492,17 @@
462
492
  <!-- predict which division titles the table of contents -->
463
493
  <!-- displays, read it and see if any mathematics landed -->
464
494
  <!-- there, exactly as "manifest-item" does per chunk -->
465
- <xsl:variable name="toc-contents" select="document(concat($tmpdir, '/', $content-dir, '/', $xhtml-dir, '/table-contents.xhtml'))"/>
495
+ <xsl:variable name="has-math">
496
+ <xsl:call-template name="file-has-math">
497
+ <xsl:with-param name="filename" select="'table-contents.xhtml'"/>
498
+ </xsl:call-template>
499
+ </xsl:variable>
466
500
  <xsl:attribute name="properties">
467
- <xsl:choose>
468
- <xsl:when test="$toc-contents//svg:svg | $toc-contents//math:math">
469
- <xsl:choose>
470
- <xsl:when test="$math.format = 'mml' or
471
- $math.format = 'kindle'">
472
- <xsl:text>nav mathml</xsl:text>
473
- </xsl:when>
474
- <xsl:when test="$math.format = 'svg'">
475
- <xsl:text>nav svg</xsl:text>
476
- </xsl:when>
477
- <xsl:otherwise>
478
- <xsl:text>nav</xsl:text>
479
- </xsl:otherwise>
480
- </xsl:choose>
481
- </xsl:when>
482
- <xsl:otherwise>
483
- <xsl:text>nav</xsl:text>
484
- </xsl:otherwise>
485
- </xsl:choose>
501
+ <xsl:text>nav</xsl:text>
502
+ <xsl:if test="($has-math = 'true') and not($manifest-math-property = '')">
503
+ <xsl:text> </xsl:text>
504
+ <xsl:value-of select="$manifest-math-property"/>
505
+ </xsl:if>
486
506
  </xsl:attribute>
487
507
  </item>
488
508
  <item id="cover-image" href="{$xhtml-dir}/{$epub-cover-dest}" properties="cover-image">
@@ -516,17 +536,12 @@
516
536
  <xsl:if test="$b-has-endnotes">
517
537
  <item id="endnotes" href="{$xhtml-dir}/{$endnote-file}"
518
538
  media-type="application/xhtml+xml">
519
- <xsl:if test="$b-endnotes-have-math">
539
+ <!-- The test examines the source, not the file, so it -->
540
+ <!-- also holds for mathematics as speech, which is -->
541
+ <!-- text and has no property to declare -->
542
+ <xsl:if test="$b-endnotes-have-math and not($manifest-math-property = '')">
520
543
  <xsl:attribute name="properties">
521
- <xsl:choose>
522
- <xsl:when test="$math.format = 'mml' or
523
- $math.format = 'kindle'">
524
- <xsl:text>mathml</xsl:text>
525
- </xsl:when>
526
- <xsl:when test="$math.format = 'svg'">
527
- <xsl:text>svg</xsl:text>
528
- </xsl:when>
529
- </xsl:choose>
544
+ <xsl:value-of select="$manifest-math-property"/>
530
545
  </xsl:attribute>
531
546
  </xsl:if>
532
547
  </item>
@@ -610,6 +625,17 @@
610
625
  </xsl:if>
611
626
  </xsl:template>
612
627
 
628
+ <!-- Whether a file of the container holds mathematics, as "true" -->
629
+ <!-- or "false". There are simply too many edge cases to decide -->
630
+ <!-- this from the structure of the source, so read the XHTML file, -->
631
+ <!-- already written, and look for an "svg" or a "math" element. -->
632
+ <!-- (Processing with page2svg makes it appear SVG images exist.) -->
633
+ <xsl:template name="file-has-math">
634
+ <xsl:param name="filename"/>
635
+ <xsl:variable name="contents" select="document(concat($tmpdir, '/', $content-dir, '/', $xhtml-dir, '/', $filename))"/>
636
+ <xsl:value-of select="boolean($contents//svg:svg | $contents//math:math)"/>
637
+ </xsl:template>
638
+
613
639
  <!-- One manifest "item" element for the context node's file -->
614
640
  <xsl:template name="manifest-item">
615
641
  <!-- Annotate manifest entries -->
@@ -620,49 +646,17 @@
620
646
  <xsl:element name="item" xmlns="http://www.idpf.org/2007/opf">
621
647
  <xsl:apply-templates select="." mode="html-id-attribute"/>
622
648
  <!-- properties are iff, so validator complains if extra -->
623
- <!-- condition on math presence for svg/mathml property -->
624
- <!-- TODO: use a parameter switch for output style -->
625
649
  <!-- Study: https://github.com/w3c/epubcheck/issues/420 -->
626
- <!-- Processing with page2svg makes it appear SVG images exist -->
627
- <!-- Set properties="svg" or properties="mathml" when a -->
628
- <!-- file contains math in one of thse formats. -->
629
- <!-- There are simply too many edge cases to do this -->
630
- <!-- based on document structure alone, so read the actual -->
631
- <!-- XHTML files we've already written and look for svg -->
632
- <!-- or math tags in them. -->
633
650
  <xsl:variable name="has-math">
634
- <xsl:variable name="contents-filename">
635
- <xsl:value-of select="$tmpdir" />
636
- <xsl:text>/</xsl:text>
637
- <xsl:value-of select="$content-dir" />
638
- <xsl:text>/</xsl:text>
639
- <xsl:value-of select="$xhtml-dir" />
640
- <xsl:text>/</xsl:text>
641
- <xsl:apply-templates select="."
642
- mode="containing-filename"/>
643
- </xsl:variable>
644
- <xsl:variable name="filedata"
645
- select="document($contents-filename)"/>
646
- <xsl:choose>
647
- <xsl:when test="$filedata//svg:svg|$filedata//math:math">
648
- <xsl:text>true</xsl:text>
649
- </xsl:when>
650
- <xsl:otherwise>
651
- <xsl:text>false</xsl:text>
652
- </xsl:otherwise>
653
- </xsl:choose>
651
+ <xsl:call-template name="file-has-math">
652
+ <xsl:with-param name="filename">
653
+ <xsl:apply-templates select="." mode="containing-filename"/>
654
+ </xsl:with-param>
655
+ </xsl:call-template>
654
656
  </xsl:variable>
655
- <xsl:variable name="b-has-math" select="$has-math = 'true'" />
656
- <xsl:if test="$b-has-math">
657
+ <xsl:if test="$has-math = 'true'">
657
658
  <xsl:attribute name="properties">
658
- <xsl:choose>
659
- <xsl:when test="$math.format = 'mml' or $math.format = 'kindle'">
660
- <xsl:text>mathml</xsl:text>
661
- </xsl:when>
662
- <xsl:when test="$math.format = 'svg'">
663
- <xsl:text>svg</xsl:text>
664
- </xsl:when>
665
- </xsl:choose>
659
+ <xsl:value-of select="$manifest-math-property"/>
666
660
  </xsl:attribute>
667
661
  </xsl:if>
668
662
  <!-- TODO: coordinate with manifest/script on xhtml extension -->
@@ -769,16 +763,6 @@
769
763
  </xsl:choose>
770
764
  </xsl:attribute>
771
765
  </cover>
772
- <!-- These may be used in automated creation of a cover image -->
773
- <title>
774
- <xsl:apply-templates select="$document-root" mode="title-simple"/>
775
- </title>
776
- <subtitle>
777
- <xsl:apply-templates select="$document-root" mode="subtitle"/>
778
- </subtitle>
779
- <author>
780
- <xsl:apply-templates select="$bibinfo/author" mode="name-list"/>
781
- </author>
782
766
  <!-- Decide what to do with preview images, etc. -->
783
767
  <images>
784
768
  <xsl:for-each select="$document-root//image">
@@ -856,11 +840,12 @@
856
840
  <exsl:document href="{$content-dir}/{$xhtml-dir}/cover-page.xhtml" method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="no">
857
841
  <html>
858
842
  <xsl:call-template name="html-theme-attributes"/>
859
- <!-- head element should not be empty -->
843
+ <!-- head element should not be empty -->
844
+ <!-- and a "title" in the "head" is text only -->
860
845
  <head>
861
846
  <meta charset="utf-8"/>
862
847
  <title>
863
- <xsl:apply-templates select="$document-root" mode="title-full"/>
848
+ <xsl:apply-templates select="$document-root" mode="title-plain"/>
864
849
  </title>
865
850
  <xsl:if test="not($b-authored-cover)">
866
851
  <xsl:call-template name="epub-kindle-css"/>
@@ -1574,8 +1559,10 @@
1574
1559
  <!-- Math -->
1575
1560
  <!-- #### -->
1576
1561
 
1577
- <!-- Pluck SVGs from the file full of them, with matching IDs -->
1578
- <xsl:template match="m|md[mrow]">
1562
+ <!-- Pluck SVGs from the file full of them, with matching IDs. -->
1563
+ <!-- Music notation ("n", "scaledeg", "timesignature", "chord") -->
1564
+ <!-- is set as inline math, so it has a representation as well. -->
1565
+ <xsl:template match="m|md[mrow]|n|scaledeg|timesignature|chord">
1579
1566
  <!-- NB: math-representation file writes with "unique-id" -->
1580
1567
  <xsl:variable name="id">
1581
1568
  <xsl:apply-templates select="." mode="unique-id"/>
@@ -102,22 +102,28 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
102
102
  <!-- we will map the *intent* of such requests as this conversion -->
103
103
  <!-- matures. -->
104
104
 
105
- <!-- PDF/UA (ISO 14289) requires every font to be embedded, so -->
106
- <!-- each font family must name a real, available font: a generic -->
107
- <!-- family (serif, monospace) would fall back to a base-14 PDF -->
105
+ <!-- PDF/UA (ISO 14289) requires every font to be embedded, so -->
106
+ <!-- each font family must name a real, available font: a generic -->
107
+ <!-- family (serif, monospace) would fall back to a base-14 PDF -->
108
108
  <!-- font, which is never embedded. Each named family must have a -->
109
- <!-- matching declaration in pretext/fop.xconf. The body is -->
110
- <!-- Latin Modern Roman and the monospace face Inconsolata; the -->
111
- <!-- symbol family is "PreTeXt Symbols", the bundled FreeSerif -->
112
- <!-- subset (see fonts/README.md ), which carries the currency -->
113
- <!-- signs, primes, geometric end-marks, and dingbats that Latin -->
114
- <!-- Modern lacks. It is named after the body font on fo:root , -->
115
- <!-- so FOP falls back to it for any glyph the body font is -->
116
- <!-- missing, and named outright where a specific symbol is drawn. -->
117
- <!-- the 12-point optical design is used for a body font size of -->
118
- <!-- 12pt or more; smaller sizes (and 11pt) use the 10-point face -->
109
+ <!-- matching declaration in pretext/fop.xconf. The body face -->
110
+ <!-- follows the publication file's pdf/@font key ($pdf-font): -->
111
+ <!-- Latin Modern Roman by default, matching the LaTeX route, in -->
112
+ <!-- its 12-point optical design for a body font size of 12pt or -->
113
+ <!-- more; or Alegreya, a book face for text-heavy documents, in -->
114
+ <!-- one design for every size. The monospace face is Inconsolata -->
115
+ <!-- for every key. The symbol family is "PreTeXt Symbols", the -->
116
+ <!-- bundled FreeSerif subset (see fonts/README.md ), which -->
117
+ <!-- carries the currency signs, primes, geometric end-marks, and -->
118
+ <!-- dingbats that the body faces lack. It is named after the -->
119
+ <!-- body font on fo:root , so FOP falls back to it for any glyph -->
120
+ <!-- the body font is missing, and named outright where a specific -->
121
+ <!-- symbol is drawn. -->
119
122
  <xsl:variable name="font-family-main">
120
123
  <xsl:choose>
124
+ <xsl:when test="$pdf-font = 'alegreya'">
125
+ <xsl:text>Alegreya</xsl:text>
126
+ </xsl:when>
121
127
  <xsl:when test="number(substring-before($font-size, 'pt')) &gt;= 12">
122
128
  <xsl:text>Latin Modern Roman 12</xsl:text>
123
129
  </xsl:when>
@@ -1012,11 +1018,13 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1012
1018
  <!-- A run-in heading is a bold inline, built by one of a few modes -->
1013
1019
  <!-- that vary in the number they show. The font style is reset, -->
1014
1020
  <!-- since the heading may land inside an italic THEOREM-LIKE -->
1015
- <!-- statement. Each ends with a period and an optional title. -->
1021
+ <!-- statement. Each has an optional title, for a mathematical -->
1022
+ <!-- block the attribution (creator and origins), and a period only -->
1023
+ <!-- when neither follows the number. -->
1016
1024
 
1017
- <!-- "heading-full": type-name, full number, and (for a THEOREM or -->
1018
- <!-- AXIOM) the attributing creator. Basic blocks and inline -->
1019
- <!-- exercises and projects. -->
1025
+ <!-- "heading-full": type-name, full number, any title, and (for a -->
1026
+ <!-- mathematical block) the attribution, as in the HTML conversion. -->
1027
+ <!-- Basic blocks and inline exercises and projects. -->
1020
1028
  <xsl:template match="*" mode="heading-full">
1021
1029
  <fo:inline font-weight="bold" font-style="normal">
1022
1030
  <xsl:apply-templates select="." mode="type-name"/>
@@ -1027,17 +1035,21 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1027
1035
  <xsl:text> </xsl:text>
1028
1036
  <xsl:value-of select="$the-number"/>
1029
1037
  </xsl:if>
1030
- <!-- attribution of a theorem or axiom, as in the HTML conversion -->
1031
- <xsl:if test="creator and (&THEOREM-FILTER; or &AXIOM-FILTER;)">
1032
- <xsl:text> (</xsl:text>
1033
- <xsl:apply-templates select="." mode="creator-full"/>
1034
- <xsl:text>)</xsl:text>
1038
+ <xsl:variable name="b-attribution" select="(creator or origins) and (&THEOREM-FILTER; or &AXIOM-FILTER; or &DEFINITION-FILTER; or &OPENPROBLEM-FILTER;)"/>
1039
+ <!-- A period after the number only when nothing follows it, -->
1040
+ <!-- as in the HTML and LaTeX conversions -->
1041
+ <xsl:if test="not(title) and not($b-attribution)">
1042
+ <xsl:text>.</xsl:text>
1035
1043
  </xsl:if>
1036
- <xsl:text>.</xsl:text>
1037
1044
  <xsl:if test="title">
1038
1045
  <xsl:text> </xsl:text>
1039
1046
  <xsl:apply-templates select="." mode="title-full"/>
1040
1047
  </xsl:if>
1048
+ <xsl:if test="$b-attribution">
1049
+ <xsl:text> (</xsl:text>
1050
+ <xsl:apply-templates select="." mode="attribution-full"/>
1051
+ <xsl:text>)</xsl:text>
1052
+ </xsl:if>
1041
1053
  </fo:inline>
1042
1054
  </xsl:template>
1043
1055
 
@@ -1267,13 +1279,16 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1267
1279
  <xsl:apply-templates select="idx | notation"/>
1268
1280
  <xsl:variable name="content" select="*[not(self::title) and not(self::idx) and not(self::notation)]"/>
1269
1281
  <xsl:variable name="last" select="$content[last()]"/>
1270
- <!-- The mark rides a closing paragraph only when that paragraph -->
1271
- <!-- holds running text alone. A paragraph that carries a display -->
1272
- <!-- ("...written as <md/>") would otherwise have its line -->
1273
- <!-- justified (to push the mark to the margin), spreading the text -->
1274
- <!-- around the display; such a block takes the mark on its own -->
1275
- <!-- line instead. -->
1276
- <xsl:variable name="b-mark-rides" select="boolean(($last[self::p] and not($last/md)) or ($last[self::statement] and $last/*[last()][self::p] and not($last/*[last()]/md)))"/>
1282
+ <!-- The mark rides the paragraph that closes the block (directly, -->
1283
+ <!-- or by closing a "statement") only when that paragraph holds -->
1284
+ <!-- running text alone. A paragraph carrying a block-level child -->
1285
+ <!-- (a display "md", a code display "cd", or a list "ol", "ul", -->
1286
+ <!-- "dl") would otherwise have "text-align-last" justified to push -->
1287
+ <!-- the mark to the margin, which spreads the text line before the -->
1288
+ <!-- block and, since the property inherits, the last line of every -->
1289
+ <!-- list item; such a block takes the mark on its own line instead. -->
1290
+ <xsl:variable name="closing-paragraph" select="$last[self::p] | $last[self::statement]/*[last()][self::p]"/>
1291
+ <xsl:variable name="b-mark-rides" select="$closing-paragraph and not($closing-paragraph/*[self::md or self::cd or self::ol or self::ul or self::dl])"/>
1277
1292
  <!-- the heading runs in to a leading paragraph, plain or in a "statement" -->
1278
1293
  <xsl:choose>
1279
1294
  <xsl:when test="$content[1][self::p] or ($content[1][self::statement] and $content[1]/*[1][self::p])">
@@ -2146,15 +2161,16 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
2146
2161
  <!-- An image is a centered block, with the authored @width -->
2147
2162
  <!-- percentage (or the documented defaults) honored by the -->
2148
2163
  <!-- common machinery, which makes an image fill its panel when -->
2149
- <!-- inside a "sidebyside". The percentage width of the graphic -->
2150
- <!-- is relative to the available width, and the image scales to -->
2151
- <!-- it, preserving the aspect ratio. Restricted to externally -->
2152
- <!-- provided and pre-generated images; the harness reports the -->
2153
- <!-- born-in-source kinds (e.g. "latex-image"), which need -->
2154
- <!-- companion image-generation components. N.B. an SVG file -->
2155
- <!-- must carry its intrinsic @width and @height: with only a -->
2156
- <!-- @viewBox, FOP assumes a square, and the drawing floats in -->
2157
- <!-- extra vertical space. -->
2164
+ <!-- it is a panel of a "sidebyside" (or the content of a -->
2165
+ <!-- "figure" panel). The percentage width of the graphic is -->
2166
+ <!-- relative to the available width where the image sits, and -->
2167
+ <!-- the image scales to it, preserving the aspect ratio. -->
2168
+ <!-- Restricted to externally provided and pre-generated images; -->
2169
+ <!-- the harness reports the born-in-source kinds (e.g. -->
2170
+ <!-- "latex-image"), which need companion image-generation -->
2171
+ <!-- components. N.B. an SVG file must carry its intrinsic -->
2172
+ <!-- @width and @height: with only a @viewBox, FOP assumes a -->
2173
+ <!-- square, and the drawing floats in extra vertical space. -->
2158
2174
  <xsl:template match="image[@source|@pi:generated]|image[latex-image]|image[sageplot]|image[asymptote]|image[pf:prefigure]|image[mermaid]">
2159
2175
  <xsl:variable name="width">
2160
2176
  <xsl:apply-templates select="." mode="get-width-percentage"/>
@@ -3204,6 +3220,13 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
3204
3220
  <xsl:apply-templates select="&STACKABLE;"/>
3205
3221
  </xsl:template>
3206
3222
 
3223
+ <!-- A "stack" within a "figure" holds subfigures, each a -->
3224
+ <!-- "figure" with its own caption, subnumbered "(a)", "(b)", -->
3225
+ <!-- ...; the enclosing figure captions the whole. -->
3226
+ <xsl:template match="figure/stack">
3227
+ <xsl:apply-templates select="figure"/>
3228
+ </xsl:template>
3229
+
3207
3230
  <!-- A "sbsgroup" is as pure a container as there can be: the -->
3208
3231
  <!-- "sidebyside" children just pile up vertically. (Common -->
3209
3232
  <!-- layout attributes on the group are consulted by each -->
@@ -3445,6 +3468,19 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
3445
3468
  <!-- implemented entirely in common, and need no FO template -->
3446
3469
  <!-- of their own here. -->
3447
3470
 
3471
+ <!-- The "text()" template of -common passes each run of prose -->
3472
+ <!-- through this hook. A keyboard apostrophe (U+0027) becomes -->
3473
+ <!-- the typographic 'RIGHT SINGLE QUOTATION MARK' (U+2019), as -->
3474
+ <!-- in the HTML conversion; TeX makes the same change on its -->
3475
+ <!-- own in the LaTeX conversion. Verbatim text ("c", "cd", -->
3476
+ <!-- "pre", "program", "kbd", and the like) is taken whole with -->
3477
+ <!-- "value-of" and never arrives here, so code keeps its -->
3478
+ <!-- straight mark. -->
3479
+ <xsl:template name="text-processing">
3480
+ <xsl:param name="text"/>
3481
+ <xsl:value-of select="str:replace($text, $apos, '&#x2019;')"/>
3482
+ </xsl:template>
3483
+
3448
3484
  <!-- An <icon> is a FontAwesome 5 glyph, as in the LaTeX route: the -->
3449
3485
  <!-- face follows iconinfo/@font-awesome-family and the glyph is -->
3450
3486
  <!-- the Private-Use codepoint iconinfo/@fa-codepoint. -->
@@ -3991,10 +4027,14 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
3991
4027
  <!-- FO "alignment-adjust": FOP raises the object by the length, -->
3992
4028
  <!-- so the (negative) drop lowers it below the baseline, exactly -->
3993
4029
  <!-- as in CSS (verified empirically, 2026-06-11). -->
3994
- <xsl:template match="m|me|men|md|mdn">
4030
+ <!-- Music notation ("n", "scaledeg", "timesignature", "chord") is -->
4031
+ <!-- LaTeX built by the -common templates and set as inline math, -->
4032
+ <!-- so it has a representation, and a placeholder, just as "m". -->
4033
+ <xsl:template match="m|me|men|md|mdn|n|scaledeg|timesignature|chord">
3995
4034
  <xsl:variable name="id">
3996
4035
  <xsl:apply-templates select="." mode="unique-id"/>
3997
4036
  </xsl:variable>
4037
+ <xsl:variable name="b-inline" select="self::m or self::n or self::scaledeg or self::timesignature or self::chord"/>
3998
4038
  <xsl:variable name="svg" select="$math-repr/pi:math[@id = $id]/div[@class = 'svg']/svg:svg"/>
3999
4039
  <xsl:variable name="speech" select="normalize-space($speech-repr/pi:math[@id = $id]/div[@class = 'speech'])"/>
4000
4040
  <!-- A display fills the full text measure only when no -->
@@ -4063,7 +4103,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
4063
4103
  </xsl:choose>
4064
4104
  </xsl:variable>
4065
4105
  <xsl:choose>
4066
- <xsl:when test="$svg and self::m">
4106
+ <xsl:when test="$svg and $b-inline">
4067
4107
  <!-- for math sitting on the baseline (e.g. a lone digit), -->
4068
4108
  <!-- MathJax writes "vertical-align: 0;", unitless, and the -->
4069
4109
  <!-- parse of the "ex" quantity comes up empty, not zero -->
@@ -4186,6 +4226,39 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
4186
4226
  <xsl:value-of select="."/>
4187
4227
  </fo:inline>
4188
4228
  </xsl:template>
4229
+ <!-- The LaTeX of a music element is built by the "inner-music" -->
4230
+ <!-- templates of the -common stylesheet, the same LaTeX MathJax -->
4231
+ <!-- receives; this mode only boxes it, as for "m" above. -->
4232
+ <xsl:template match="n|scaledeg|timesignature|chord" mode="math-placeholder">
4233
+ <fo:inline font-family="{$font-family-monospace}" border="solid 0.5pt #888888" padding-left="2pt" padding-right="2pt">
4234
+ <xsl:apply-templates select="." mode="inner-music"/>
4235
+ </fo:inline>
4236
+ </xsl:template>
4237
+
4238
+ <!-- Accidentals in prose ("sharp", "flat", and so on, outside any -->
4239
+ <!-- note or chord); the -common templates for the elements call -->
4240
+ <!-- these by name. The body fonts lack the glyphs, and FOP falls -->
4241
+ <!-- back to another face only for a whole word, so each is set -->
4242
+ <!-- outright in the symbol font, as the end-marks are. FOP cannot -->
4243
+ <!-- address a character beyond the Basic Multilingual Plane (it -->
4244
+ <!-- mangles the surrogate pair), so the double sharp and double -->
4245
+ <!-- flat, U+1D12A and U+1D12B, are the single characters doubled, -->
4246
+ <!-- as the MathJax representations also render them. -->
4247
+ <xsl:template name="doublesharp">
4248
+ <fo:inline font-family="{$font-family-symbol}">&#x266F;&#x266F;</fo:inline>
4249
+ </xsl:template>
4250
+ <xsl:template name="sharp">
4251
+ <fo:inline font-family="{$font-family-symbol}">&#x266F;</fo:inline>
4252
+ </xsl:template>
4253
+ <xsl:template name="natural">
4254
+ <fo:inline font-family="{$font-family-symbol}">&#x266E;</fo:inline>
4255
+ </xsl:template>
4256
+ <xsl:template name="flat">
4257
+ <fo:inline font-family="{$font-family-symbol}">&#x266D;</fo:inline>
4258
+ </xsl:template>
4259
+ <xsl:template name="doubleflat">
4260
+ <fo:inline font-family="{$font-family-symbol}">&#x266D;&#x266D;</fo:inline>
4261
+ </xsl:template>
4189
4262
 
4190
4263
  <!-- Assembly rewrites every display to "md", so that is the only -->
4191
4264
  <!-- form seen here. Each "mrow" is one line of the display: emit -->
@@ -4637,6 +4710,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
4637
4710
  self::nbsp or self::ndash or self::mdash or self::lsq or self::rsq or self::lq or self::rq or self::ldblbracket or self::rdblbracket or self::langle or self::rangle or self::ellipsis or self::midpoint or self::swungdash or self::permille or self::pilcrow or self::section-mark or self::minus or self::times or self::solidus or self::obelus or self::plusminus or self::copyright or self::phonomark or self::copyleft or self::registered or self::trademark or self::servicemark or self::degree or self::prime or self::dblprime or
4638
4711
  self::q or self::sq or self::dblbrackets or self::angles or
4639
4712
  self::c or self::cline or self::tag or self::tage or self::attr or self::today or self::timeofday or self::pi:localize or
4713
+ self::sharp or self::flat or self::natural or self::doublesharp or self::doubleflat or
4640
4714
  self::xref or self::index-list or self::notation-list or self::list-of)]">
4641
4715
  <xsl:message>PTX:FO-TODO: <xsl:value-of select="local-name()"/> (child of "<xsl:value-of select="local-name(parent::*)"/>")</xsl:message>
4642
4716
  <xsl:apply-templates select="*"/>