@pretextbook/pretext-html 0.13.0 → 0.15.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.
@@ -228,6 +228,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
228
228
  <xsl:variable name="b-has-sage" select="boolean($document-root//sage)"/>
229
229
  <xsl:variable name="b-has-sfrac" select="boolean($document-root//m[contains(text(),'sfrac')] or $document-root//mrow[contains(text(),'sfrac')])" />
230
230
  <xsl:variable name="b-has-geogebra" select="boolean($document-root//interactive[@platform='geogebra'])"/>
231
+ <xsl:variable name="b-has-doenetml" select="boolean($document-root//interactive[@platform='doenetml'])"/>
231
232
  <xsl:variable name="b-has-mermaid" select="boolean($document-root//image[mermaid]|/image[mermaid])"/>
232
233
  <!-- 2018-04-06: jsxgraph deprecated -->
233
234
  <xsl:variable name="b-has-jsxgraph" select="boolean($document-root//jsxgraph)"/>
@@ -244,6 +245,15 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
244
245
  <xsl:variable name="ol-markers">
245
246
  <ol-markers>
246
247
  <xsl:apply-templates select="$document-root//ol[@marker and count(. | key('marker-key', @marker)[1]) = 1]" mode="ol-markers"/>
248
+ <!-- A legacy exercise-parts list letters as "(a)" with no -->
249
+ <!-- authored @marker; it joins the index as a reserved entry, -->
250
+ <!-- so one mechanism serves it, unless an authored "(a)" is -->
251
+ <!-- already present to share. The parenthesized letters are -->
252
+ <!-- LaTeX's custom for second-level lists, which PreTeXt -->
253
+ <!-- matches in every output (assembly stamps the adornments). -->
254
+ <xsl:if test="$document-root//ol[not(@marker) and @pi:format-code = 'a' and @pi:ordered-list-level = '1'] and not($document-root//ol[@marker = '(a)'])">
255
+ <ol-marker pi:format-code="a" marker="(a)" pi:marker-prefix="(" pi:marker-suffix=")" name="ptx-marker-0"/>
256
+ </xsl:if>
247
257
  </ol-markers>
248
258
  </xsl:variable>
249
259
  <!-- Following should be more efficient than 'select="boolean($document-root//ol[@marker])"' -->
@@ -350,12 +360,6 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
350
360
  <xsl:if test="not($b-subsetting) and not($b-portable-html)">
351
361
  <xsl:apply-templates select="." mode="make-xref-knowls"/>
352
362
  </xsl:if>
353
- <!-- custom ol marker css production -->
354
- <!-- A CDN cannot host these styles, since they are derived from the -->
355
- <!-- source. CDN builds get them inline instead, see "css-common". -->
356
- <xsl:if test="not($b-subsetting) and not($b-cdn-resources)">
357
- <xsl:call-template name="ol-marker-styles"/>
358
- </xsl:if>
359
363
  </xsl:template>
360
364
 
361
365
  <!-- However, some PTX document types do not have -->
@@ -2074,6 +2078,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
2074
2078
  <!-- this message, locate the apply-templates chain -->
2075
2079
  <!-- that omitted the parameter and add it. -->
2076
2080
  <xsl:message>PTX:BUG: "hN" template reached without a $heading-level parameter on element &lt;<xsl:value-of select="local-name(.)"/>&gt; at <xsl:for-each select="ancestor::*"><xsl:value-of select="local-name(.)"/><xsl:text>/</xsl:text></xsl:for-each><xsl:value-of select="local-name(.)"/>; defaulting to h1</xsl:message>
2081
+ <xsl:apply-templates select="." mode="location-report"/>
2077
2082
  <xsl:text>1</xsl:text>
2078
2083
  </xsl:otherwise>
2079
2084
  </xsl:choose>
@@ -6169,14 +6174,14 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
6169
6174
  <!-- Utility templates to translate PTX -->
6170
6175
  <!-- enumeration style to HTML list-style-type -->
6171
6176
  <xsl:template match="ol|ol-marker" mode="html-list-class">
6172
- <xsl:variable name="mbx-format-code" select="./@pi:format-code" />
6177
+ <xsl:variable name="ptx-format-code" select="./@pi:format-code" />
6173
6178
  <xsl:choose>
6174
- <xsl:when test="$mbx-format-code = '0'">decimal</xsl:when>
6175
- <xsl:when test="$mbx-format-code = '1'">decimal</xsl:when>
6176
- <xsl:when test="$mbx-format-code = 'a'">lower-alpha</xsl:when>
6177
- <xsl:when test="$mbx-format-code = 'A'">upper-alpha</xsl:when>
6178
- <xsl:when test="$mbx-format-code = 'i'">lower-roman</xsl:when>
6179
- <xsl:when test="$mbx-format-code = 'I'">upper-roman</xsl:when>
6179
+ <xsl:when test="$ptx-format-code = '0'">decimal</xsl:when>
6180
+ <xsl:when test="$ptx-format-code = '1'">decimal</xsl:when>
6181
+ <xsl:when test="$ptx-format-code = 'a'">lower-alpha</xsl:when>
6182
+ <xsl:when test="$ptx-format-code = 'A'">upper-alpha</xsl:when>
6183
+ <xsl:when test="$ptx-format-code = 'i'">lower-roman</xsl:when>
6184
+ <xsl:when test="$ptx-format-code = 'I'">upper-roman</xsl:when>
6180
6185
  <xsl:otherwise>
6181
6186
  <xsl:message>PTX:BUG: bad ordered list label format code in HTML conversion</xsl:message>
6182
6187
  </xsl:otherwise>
@@ -6184,14 +6189,12 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
6184
6189
  </xsl:template>
6185
6190
 
6186
6191
  <xsl:template match="ul" mode="html-list-class">
6187
- <xsl:variable name="mbx-format-code">
6188
- <xsl:apply-templates select="." mode="format-code" />
6189
- </xsl:variable>
6192
+ <xsl:variable name="ptx-format-code" select="./@pi:format-code"/>
6190
6193
  <xsl:choose>
6191
- <xsl:when test="$mbx-format-code = 'disc'">disc</xsl:when>
6192
- <xsl:when test="$mbx-format-code = 'circle'">circle</xsl:when>
6193
- <xsl:when test="$mbx-format-code = 'square'">square</xsl:when>
6194
- <xsl:when test="$mbx-format-code = 'none'">no-marker</xsl:when>
6194
+ <xsl:when test="$ptx-format-code = 'disc'">disc</xsl:when>
6195
+ <xsl:when test="$ptx-format-code = 'circle'">circle</xsl:when>
6196
+ <xsl:when test="$ptx-format-code = 'square'">square</xsl:when>
6197
+ <xsl:when test="$ptx-format-code = 'none'">no-marker</xsl:when>
6195
6198
  <xsl:otherwise>
6196
6199
  <xsl:message>PTX:BUG: bad unordered list label format code in HTML conversion</xsl:message>
6197
6200
  </xsl:otherwise>
@@ -6205,30 +6208,12 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
6205
6208
  <xsl:template match="ol|ul">
6206
6209
  <xsl:param name="b-original" select="true()" />
6207
6210
  <xsl:param name="heading-level"/>
6208
- <!-- need to switch on 0-1 for ol Arabic -->
6209
- <!-- no harm if called on "ul" -->
6210
- <xsl:variable name="mbx-format-code">
6211
- <xsl:choose>
6212
- <xsl:when test="self::ol">
6213
- <xsl:value-of select="./@pi:format-code" />
6214
- </xsl:when>
6215
- <xsl:otherwise>
6216
- <xsl:apply-templates select="." mode="format-code" />
6217
- </xsl:otherwise>
6218
- </xsl:choose>
6219
- </xsl:variable>
6211
+ <xsl:variable name="ptx-format-code" select="./@pi:format-code"/>
6220
6212
  <!-- newline inserted to encourage formatted output -->
6221
6213
  <xsl:text>&#xa;</xsl:text>
6222
6214
  <xsl:element name="{local-name(.)}">
6223
6215
  <xsl:attribute name="class">
6224
6216
  <xsl:apply-templates select="." mode="html-list-class" />
6225
- <xsl:variable name="ol-marker-class">
6226
- <xsl:apply-templates select="." mode="ol-marker-class" />
6227
- </xsl:variable>
6228
- <xsl:if test="not($ol-marker-class = '')">
6229
- <xsl:text> </xsl:text>
6230
- <xsl:value-of select="$ol-marker-class"/>
6231
- </xsl:if>
6232
6217
  <xsl:variable name="cols-class-name">
6233
6218
  <!-- HTML-specific, but in pretext-common.xsl -->
6234
6219
  <xsl:apply-templates select="." mode="number-cols-CSS-class"/>
@@ -6238,10 +6223,22 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
6238
6223
  <xsl:value-of select="$cols-class-name"/>
6239
6224
  </xsl:if>
6240
6225
  </xsl:attribute>
6226
+ <!-- a custom marker is a named "@counter-style" rule, inlined -->
6227
+ <!-- with the page's CSS, referenced from right here -->
6228
+ <xsl:variable name="ol-marker-name">
6229
+ <xsl:apply-templates select="." mode="ol-marker-name"/>
6230
+ </xsl:variable>
6231
+ <xsl:if test="not($ol-marker-name = '')">
6232
+ <xsl:attribute name="style">
6233
+ <xsl:text>list-style: </xsl:text>
6234
+ <xsl:value-of select="$ol-marker-name"/>
6235
+ <xsl:text>;</xsl:text>
6236
+ </xsl:attribute>
6237
+ </xsl:if>
6241
6238
  <xsl:attribute name="id">
6242
6239
  <xsl:apply-templates select="." mode="html-id" />
6243
6240
  </xsl:attribute>
6244
- <xsl:if test="$mbx-format-code = '0'">
6241
+ <xsl:if test="$ptx-format-code = '0'">
6245
6242
  <xsl:attribute name="start">
6246
6243
  <xsl:text>0</xsl:text>
6247
6244
  </xsl:attribute>
@@ -6253,20 +6250,23 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
6253
6250
  </xsl:element>
6254
6251
  </xsl:template>
6255
6252
 
6256
- <xsl:template match="ol[@marker]" mode="ol-marker-class">
6253
+ <xsl:template match="ol[@marker]" mode="ol-marker-name">
6257
6254
  <xsl:variable name="marker-value" select="./@marker" />
6258
6255
  <xsl:for-each select="exsl:node-set($ol-markers)">
6259
6256
  <!-- Should be only one match since ol marker -->
6260
6257
  <!-- index node set contains no duplicates -->
6261
- <xsl:value-of select="key('marker-key', $marker-value)[1]/@classname"/>
6258
+ <xsl:value-of select="key('marker-key', $marker-value)[1]/@name"/>
6262
6259
  </xsl:for-each >
6263
6260
  </xsl:template>
6264
6261
 
6265
- <xsl:template match="ol[not(@marker) and @pi:format-code = 'a' and @pi:ordered-list-level = '1']" mode="ol-marker-class">
6266
- <xsl:text>lower-alpha-level-1</xsl:text>
6262
+ <!-- the reserved "(a)" entry, or an authored twin, by the same lookup -->
6263
+ <xsl:template match="ol[not(@marker) and @pi:format-code = 'a' and @pi:ordered-list-level = '1']" mode="ol-marker-name">
6264
+ <xsl:for-each select="exsl:node-set($ol-markers)">
6265
+ <xsl:value-of select="key('marker-key', '(a)')[1]/@name"/>
6266
+ </xsl:for-each>
6267
6267
  </xsl:template>
6268
6268
 
6269
- <xsl:template match="ol|ul" mode="ol-marker-class"/>
6269
+ <xsl:template match="ol|ul" mode="ol-marker-name"/>
6270
6270
 
6271
6271
  <xsl:template match="ol[@marker]" mode="ol-markers">
6272
6272
  <xsl:element name="ol-marker">
@@ -6274,38 +6274,39 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
6274
6274
  <xsl:copy-of select="@marker"/>
6275
6275
  <xsl:copy-of select="@pi:marker-prefix"/>
6276
6276
  <xsl:copy-of select="@pi:marker-suffix"/>
6277
- <xsl:attribute name="classname">
6278
- <xsl:text>ol-marker-</xsl:text>
6277
+ <xsl:attribute name="name">
6278
+ <xsl:text>ptx-marker-</xsl:text>
6279
6279
  <xsl:value-of select="position()" />
6280
6280
  </xsl:attribute>
6281
6281
  </xsl:element>
6282
6282
  </xsl:template>
6283
6283
 
6284
- <!-- Creates custom formatting for each unique ol/@marker -->
6284
+ <!-- One "@counter-style" rule per distinct marker. The author's -->
6285
+ <!-- prefix and suffix become CSS strings, escaped; the suffix gains -->
6286
+ <!-- the trailing space that separates a marker from its item. Each -->
6287
+ <!-- list references its rule by name from a "style" attribute, so -->
6288
+ <!-- these rules are the only shared CSS a custom marker needs. -->
6289
+ <!-- They cannot be per-list: an at-rule only lives in a stylesheet. -->
6290
+ <!-- Should WebKit ever support "content" on "::marker" (WebKit bug -->
6291
+ <!-- 204163), one static theme rule reading custom properties could -->
6292
+ <!-- replace all of this, and markers would be entirely per-list -->
6293
+ <!-- inline, with no shared rules and no marker index at all. -->
6285
6294
  <xsl:template match="ol-marker" mode="ol-marker-style">
6286
- <!-- format child li elements according to marker prefix/code/suffix -->
6287
- <xsl:text>ol.</xsl:text>
6288
- <xsl:value-of select="./@classname"/>
6289
- <xsl:text> &gt; li::marker { content: &quot;</xsl:text>
6290
- <xsl:value-of select="./@pi:marker-prefix" />
6291
- <xsl:text>&quot;counter(list-item,</xsl:text>
6295
+ <xsl:text>@counter-style </xsl:text>
6296
+ <xsl:value-of select="./@name"/>
6297
+ <xsl:text> { system: extends </xsl:text>
6292
6298
  <xsl:apply-templates select="." mode="html-list-class" />
6293
- <xsl:text>)&quot;</xsl:text>
6294
- <xsl:value-of select="./@pi:marker-suffix" />
6295
- <xsl:text> &quot;; }&#xa;</xsl:text>
6299
+ <xsl:text>; prefix: '</xsl:text>
6300
+ <xsl:call-template name="css-string-escape">
6301
+ <xsl:with-param name="text" select="./@pi:marker-prefix"/>
6302
+ </xsl:call-template>
6303
+ <xsl:text>'; suffix: '</xsl:text>
6304
+ <xsl:call-template name="css-string-escape">
6305
+ <xsl:with-param name="text" select="./@pi:marker-suffix"/>
6306
+ </xsl:call-template>
6307
+ <xsl:text> '; }&#xa;</xsl:text>
6296
6308
  </xsl:template>
6297
6309
 
6298
- <!-- CSS file for custom ol markers -->
6299
- <xsl:template name="ol-marker-styles">
6300
- <!-- We don't produce a file if it will be empty. This would -->
6301
- <!-- "naturally" be the case, but we have a boolean anyway. -->
6302
- <xsl:if test="$b-needs-custom-marker-css">
6303
- <xsl:variable name="ol-marker-nodes" select="exsl:node-set($ol-markers)" />
6304
- <exsl:document href="{$html.css.dir}/ol-markers.css" method="text">
6305
- <xsl:apply-templates select="$ol-marker-nodes//ol-marker" mode="ol-marker-style" />
6306
- </exsl:document>
6307
- </xsl:if>
6308
- </xsl:template>
6309
6310
 
6310
6311
  <!-- We let CSS react to narrow titles for dl -->
6311
6312
  <!-- But no support for multiple columns -->
@@ -10212,6 +10213,10 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
10212
10213
  <xsl:attribute name="src">
10213
10214
  <xsl:apply-templates select="." mode="iframe-filename" />
10214
10215
  </xsl:attribute>
10216
+ <!-- how the coordinator script recognizes an activity it manages -->
10217
+ <xsl:if test="(@platform = 'doenetml') and $b-doenetml-coordinator">
10218
+ <xsl:attribute name="data-doenet-coordinate">true</xsl:attribute>
10219
+ </xsl:if>
10215
10220
  <xsl:apply-templates select="." mode="iframe-accessibility-attributes"/>
10216
10221
  </iframe>
10217
10222
  <!-- possibly give a long description -->
@@ -10372,6 +10377,20 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
10372
10377
  <script src="{$d3-library-url}"></script>
10373
10378
  </xsl:template>
10374
10379
 
10380
+ <!-- The version of DoenetML a document asks for, absent any request from -->
10381
+ <!-- an individual "interactive". Also the version of the coordinator -->
10382
+ <!-- script a page carrying DoenetML activities loads. -->
10383
+ <xsl:variable name="doenetml-document-version">
10384
+ <xsl:choose>
10385
+ <xsl:when test="$docinfo/doenetml/@version">
10386
+ <xsl:value-of select="$docinfo/doenetml/@version"/>
10387
+ </xsl:when>
10388
+ <xsl:otherwise>
10389
+ <xsl:text>latest</xsl:text>
10390
+ </xsl:otherwise>
10391
+ </xsl:choose>
10392
+ </xsl:variable>
10393
+
10375
10394
  <!-- DoenetML header libraries -->
10376
10395
  <xsl:template match="interactive[@platform = 'doenetml']" mode="header-libraries">
10377
10396
  <xsl:variable name="doenet-version">
@@ -10379,11 +10398,8 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
10379
10398
  <xsl:when test="@version">
10380
10399
  <xsl:value-of select="@version"/>
10381
10400
  </xsl:when>
10382
- <xsl:when test="$docinfo/doenetml/@version">
10383
- <xsl:value-of select="$docinfo/doenetml/@version"/>
10384
- </xsl:when>
10385
10401
  <xsl:otherwise>
10386
- <xsl:text>latest</xsl:text>
10402
+ <xsl:value-of select="$doenetml-document-version"/>
10387
10403
  </xsl:otherwise>
10388
10404
  </xsl:choose>
10389
10405
  </xsl:variable>
@@ -10700,6 +10716,15 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
10700
10716
  </xsl:choose>
10701
10717
  <xsl:text>,&#xa;</xsl:text>
10702
10718
  </xsl:if>
10719
+ <!-- Unlike the parameters above, this one is the publisher's rather than -->
10720
+ <!-- the author's. GeoGebra renders a preview image and a play button in -->
10721
+ <!-- place of the applet, and only starts the applet when a reader presses -->
10722
+ <!-- it, so a page carrying several applets need not start them all at -->
10723
+ <!-- once. GeoGebra's own default is no button, which is also ours, so -->
10724
+ <!-- nothing is emitted unless a publisher asks for it. -->
10725
+ <xsl:if test="$b-geogebra-play-button">
10726
+ <xsl:text>playButton: true,&#xa;</xsl:text>
10727
+ </xsl:if>
10703
10728
  <xsl:text>width:</xsl:text><xsl:value-of select="$material-width" />
10704
10729
  <xsl:text>,&#xa;</xsl:text>
10705
10730
  <xsl:text>height:</xsl:text><xsl:value-of select="$material-height" />
@@ -10717,6 +10742,24 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
10717
10742
  <xsl:value-of select="$applet-parameters" />
10718
10743
  <xsl:text>, true);&#xa;</xsl:text>
10719
10744
 
10745
+ <!-- GeoGebra draws its play button in front of a preview image, and it -->
10746
+ <!-- has one to offer only for an applet it hosts itself. An applet -->
10747
+ <!-- built from a file, or written from scratch, gets an empty box. A -->
10748
+ <!-- screenshot of every interactive is made for static output, so we -->
10749
+ <!-- hand GeoGebra that one, and then every applet alike shows what a -->
10750
+ <!-- reader is being invited to start. The second and third arguments -->
10751
+ <!-- would be a loading indicator and the button's own image; GeoGebra -->
10752
+ <!-- supplies the button, and no indicator is wanted in front of a -->
10753
+ <!-- picture of the applet itself. -->
10754
+ <xsl:if test="$b-geogebra-play-button">
10755
+ <xsl:value-of select="$applet-name"/>
10756
+ <xsl:text>.setPreviewImage('</xsl:text>
10757
+ <xsl:value-of select="$generated-directory"/>
10758
+ <xsl:text>preview/</xsl:text>
10759
+ <xsl:apply-templates select="ancestor::interactive" mode="unique-id"/>
10760
+ <xsl:text>-preview.png', null, null);&#xa;</xsl:text>
10761
+ </xsl:if>
10762
+
10720
10763
  <xsl:text>resolve(</xsl:text><xsl:value-of select="$applet-name" /><xsl:text>);})&#xa;</xsl:text>
10721
10764
  <xsl:text>.then((</xsl:text><xsl:value-of select="$applet-name" /><xsl:text>) => {&#xa;</xsl:text>
10722
10765
  <!-- inject the applet into the div below -->
@@ -11539,6 +11582,10 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
11539
11582
  <xsl:call-template name="scorm-js"/>
11540
11583
  <xsl:call-template name="diagcess-header"/>
11541
11584
  <xsl:call-template name="lti-iframe-resizer"/>
11585
+ <!-- NB: deliberately not in the iframe head cache above - the -->
11586
+ <!-- coordinator belongs on the page that *holds* the activities, -->
11587
+ <!-- and a standalone page holds the one it was extracted for. -->
11588
+ <xsl:call-template name="doenetml-coordinator" />
11542
11589
  </xsl:variable>
11543
11590
 
11544
11591
  <!-- Content used by simple-file-wrap -->
@@ -14616,6 +14663,51 @@ TODO:
14616
14663
  </xsl:if>
14617
14664
  </xsl:template>
14618
14665
 
14666
+ <!-- DoenetML coordinator -->
14667
+ <!-- A "coordinator" script, served alongside the DoenetML bundle that -->
14668
+ <!-- the activities already load, takes charge of a page's activity -->
14669
+ <!-- "iframe"s so that a page carrying many of them need not run them -->
14670
+ <!-- all at once. See publisher-variables.xsl for what it does and for -->
14671
+ <!-- the publisher's control over it. The activity pages need no -->
14672
+ <!-- cooperation - the coordinator marks each activity's URL and the -->
14673
+ <!-- bundle recognizes the mark - so this one script tag is all of it. -->
14674
+ <xsl:template name="doenetml-coordinator">
14675
+ <xsl:if test="$b-has-doenetml and $b-doenetml-coordinator">
14676
+ <xsl:variable name="doenet-coordinator-url">
14677
+ <xsl:text>https://cdn.jsdelivr.net/npm/@doenet/standalone@</xsl:text>
14678
+ <xsl:value-of select="$doenetml-document-version"/>
14679
+ <xsl:text>/coordinator.js</xsl:text>
14680
+ </xsl:variable>
14681
+ <!-- A document pinned to a DoenetML version from 0.7.21 through -->
14682
+ <!-- 0.7.24 gets a coordinator that restores a parked activity's -->
14683
+ <!-- work itself, racing a host that restores saved work of its -->
14684
+ <!-- own - and the older copy can win, replacing work a reader -->
14685
+ <!-- just did. The publisher may not have read the paragraph in -->
14686
+ <!-- the Guide that says so, and both facts are visible here, so -->
14687
+ <!-- warn. A partial pin like "0.7" floats to the newest release -->
14688
+ <!-- and is safe; its patch part is empty, and fails the numeric -->
14689
+ <!-- comparisons below. -->
14690
+ <xsl:if test="$b-host-runestone or $b-host-scorm">
14691
+ <xsl:variable name="doenetml-pin-patch" select="substring-after(substring-after($doenetml-document-version, '.'), '.')"/>
14692
+ <xsl:if test="(substring-before($doenetml-document-version, '.') = '0') and (substring-before(substring-after($doenetml-document-version, '.'), '.') = '7') and (number($doenetml-pin-patch) &gt;= 21) and (number($doenetml-pin-patch) &lt;= 24)">
14693
+ <xsl:message>PTX:WARNING: this document pins DoenetML version <xsl:value-of select="$doenetml-document-version"/>, whose activity coordinator can replace a reader's saved work with an older copy when the book is hosted on Runestone or as SCORM. Pin version 0.7.25 or later, or set the "coordinator" attribute of the "doenetml" element of the publication file to "no"</xsl:message>
14694
+ </xsl:if>
14695
+ </xsl:if>
14696
+ <!-- The selector confines the script to DoenetML activities (see -->
14697
+ <!-- the "data-doenet-coordinate" attribute placed on their -->
14698
+ <!-- "iframe"s); the script's own default would also sweep up every -->
14699
+ <!-- "-if.html" iframe, which for PreTeXt means every other -->
14700
+ <!-- platform's interactive too. -->
14701
+ <!-- Two notes on the tag itself: it is a classic script, so -->
14702
+ <!-- "document.currentScript" still supplies its options under -->
14703
+ <!-- "defer", which keeps a CDN fetch from blocking every page of -->
14704
+ <!-- the book; and the script reads the shared-core-workers value -->
14705
+ <!-- as anything but the string "false", so the publisher's "no" -->
14706
+ <!-- must be stringified as "false" rather than passed through. -->
14707
+ <script defer="defer" src="{$doenet-coordinator-url}" data-iframe-selector="iframe[data-doenet-coordinate]" data-max-live-viewers="{$doenetml-max-live-viewers}" data-max-concurrent-boots="{$doenetml-max-concurrent-boots}" data-shared-core-workers="{$b-doenetml-shared-core-workers}"></script>
14708
+ </xsl:if>
14709
+ </xsl:template>
14710
+
14619
14711
  <!-- JSXGraph -->
14620
14712
  <xsl:template name="jsxgraph">
14621
14713
  <xsl:if test="$b-has-jsxgraph">
@@ -14660,22 +14752,16 @@ TODO:
14660
14752
 
14661
14753
  <!-- CSS header -->
14662
14754
  <xsl:template name="css-common">
14663
- <!-- Temporary until css handling overhaul by ascholer complete -->
14755
+ <!-- Custom list markers are "@counter-style" rules derived from the -->
14756
+ <!-- source, one per distinct marker, referenced by name from each -->
14757
+ <!-- list's "style" attribute. Inlined unconditionally: they are -->
14758
+ <!-- tiny, they cannot live on a CDN, and portable HTML has no place -->
14759
+ <!-- to link out to anyway. -->
14664
14760
  <xsl:if test="$b-needs-custom-marker-css">
14665
- <xsl:choose>
14666
- <!-- These styles are derived from the source, so they are not on -->
14667
- <!-- the CDN and "$html.css.dir" does not point at them. Inline -->
14668
- <!-- them: there is one short rule per unique author-supplied -->
14669
- <!-- marker, and portable HTML has no place to link out to anyway. -->
14670
- <xsl:when test="$b-cdn-resources">
14671
- <style>
14672
- <xsl:apply-templates select="exsl:node-set($ol-markers)//ol-marker" mode="ol-marker-style"/>
14673
- </style>
14674
- </xsl:when>
14675
- <xsl:otherwise>
14676
- <link href="{$html.css.dir}/ol-markers.css" rel="stylesheet" type="text/css"/>
14677
- </xsl:otherwise>
14678
- </xsl:choose>
14761
+ <style>
14762
+ <xsl:text>&#xa;</xsl:text>
14763
+ <xsl:apply-templates select="exsl:node-set($ol-markers)//ol-marker" mode="ol-marker-style"/>
14764
+ </style>
14679
14765
  </xsl:if>
14680
14766
  <!-- If extra CSS is specified, then unpack multiple CSS files -->
14681
14767
  <xsl:if test="not($html.css.extra = '')">
@@ -354,6 +354,10 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
354
354
  <xsl:text>.mathbook-content table tr.header-vertical th {writing-mode: vertical-rl; padding-left: 2em;}&#xa;</xsl:text>
355
355
  <xsl:text>.mathbook-content .sbspanel img {max-width: 100%;}&#xa;</xsl:text>
356
356
  <xsl:text>.mathbook-content .tablenotes {list-style: none; padding-left: 0;}&#xa;</xsl:text>
357
+ <!-- custom list markers, one "@counter-style" rule per -->
358
+ <!-- distinct marker, referenced from each list's -->
359
+ <!-- "style" attribute -->
360
+ <xsl:apply-templates select="exsl:node-set($ol-markers)//ol-marker" mode="ol-marker-style"/>
357
361
  <xsl:text>&lt;/style&gt;</xsl:text>
358
362
  <xsl:call-template name="end-string" />
359
363
  </xsl:with-param>
@@ -5733,9 +5733,7 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
5733
5733
  </xsl:template>
5734
5734
 
5735
5735
  <xsl:template match="ul" mode="latex-list-label">
5736
- <xsl:variable name="format-code">
5737
- <xsl:apply-templates select="." mode="format-code" />
5738
- </xsl:variable>
5736
+ <xsl:variable name="format-code" select="./@pi:format-code"/>
5739
5737
  <xsl:choose>
5740
5738
  <xsl:when test="$format-code = 'disc'">\ptxlistdisc</xsl:when>
5741
5739
  <xsl:when test="$format-code = 'circle'">\ptxlistcircle</xsl:when>
@@ -5748,26 +5746,6 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
5748
5746
  </xsl:template>
5749
5747
 
5750
5748
 
5751
- <!-- Utility template to translate unordered -->
5752
- <!-- list level to HTML list-style-type -->
5753
- <!-- This is similar to Firefox default choices -->
5754
- <!-- but different in the fourth slot -->
5755
- <!-- disc, circle, square, disc -->
5756
- <xsl:template match="*" mode="latex-unordered-list-label-default">
5757
- <xsl:variable name="level">
5758
- <xsl:apply-templates select="." mode="unordered-list-level" />
5759
- </xsl:variable>
5760
- <xsl:choose>
5761
- <xsl:when test="$level='0'">\ptxlistdisc</xsl:when>
5762
- <xsl:when test="$level='1'">\ptxlistcircle</xsl:when>
5763
- <xsl:when test="$level='2'">\ptxlistsquare</xsl:when>
5764
- <xsl:when test="$level='3'">\ptxlistdisc</xsl:when>
5765
- <xsl:otherwise>
5766
- <xsl:message>PTX:ERROR: unordered list is more than 4 levels deep</xsl:message>
5767
- </xsl:otherwise>
5768
- </xsl:choose>
5769
- </xsl:template>
5770
-
5771
5749
  <!-- Lists themselves -->
5772
5750
  <!-- If columns are specified, we -->
5773
5751
  <!-- wrap in the multicolumn environment -->
@@ -525,6 +525,107 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
525
525
  </p>
526
526
  </xsl:template>
527
527
 
528
+ <!-- A paragraph containing displays - lists ("ol", "ul", "dl"), -->
529
+ <!-- display mathematics ("md"), or code display ("cd") - cannot -->
530
+ <!-- be realized as a single HTML "p". Each display renders as -->
531
+ <!-- an element that HTML forbids inside a "p" (a list, a "pre", -->
532
+ <!-- a "div" of online mathematics), and a browser recovers by -->
533
+ <!-- closing the paragraph at the display, leaving the remainder -->
534
+ <!-- orphaned outside any paragraph. So, just as in the HTML -->
535
+ <!-- conversion, such a paragraph is exploded: each maximal run -->
536
+ <!-- of inline content becomes a "p" (an empty run produces -->
537
+ <!-- nothing at all), with the displays standing in between. -->
538
+ <!-- (With embedded mathematics a display is a "span", legal -->
539
+ <!-- within a "p" and block-level only by styling, but it is -->
540
+ <!-- exploded identically: the presentation is the same and the -->
541
+ <!-- template stays uniform.) -->
542
+ <!-- -->
543
+ <!-- This realization is demanded by the output format alone; it -->
544
+ <!-- is not the undoing of upstream normalization. An author may -->
545
+ <!-- place a display mid-paragraph, so the explosion is necessary -->
546
+ <!-- even when no paragraph is ever manufactured. Conversely, -->
547
+ <!-- when the assembly wraps a bare list on a "slide" in a -->
548
+ <!-- paragraph, so the internal tree presents the main grammar's -->
549
+ <!-- one shape to every consumer, that paragraph's inline runs -->
550
+ <!-- are all empty and the exploded output is exactly the bare -->
551
+ <!-- list again. The two maneuvers are complementary: normalize -->
552
+ <!-- toward the grammar internally, adapt to the medium at output. -->
553
+ <!-- -->
554
+ <!-- A paused paragraph must advance as a single unit, so its -->
555
+ <!-- exploded parts ride together in one container carrying the -->
556
+ <!-- "fragment" class. -->
557
+ <xsl:template match="p[ol|ul|dl|md[mrow]|cd]">
558
+ <xsl:choose>
559
+ <xsl:when test="@pause = 'yes'">
560
+ <div class="fragment">
561
+ <xsl:apply-templates select="." mode="exploded-paragraph"/>
562
+ </div>
563
+ </xsl:when>
564
+ <xsl:otherwise>
565
+ <xsl:apply-templates select="." mode="exploded-paragraph"/>
566
+ </xsl:otherwise>
567
+ </xsl:choose>
568
+ </xsl:template>
569
+
570
+ <!-- The explosion itself, patterned on the HTML conversion's -->
571
+ <!-- template for a "p" with displays, simplified: no HTML id, no -->
572
+ <!-- permalink, no knowl machinery on the pieces of a slide. -->
573
+ <xsl:template match="p" mode="exploded-paragraph">
574
+ <xsl:variable name="displays" select="ol|ul|dl|md[mrow]|cd"/>
575
+ <!-- content prior to the first display; if empty -->
576
+ <!-- we do not manufacture an empty paragraph -->
577
+ <xsl:variable name="initial" select="$displays[1]/preceding-sibling::*|$displays[1]/preceding-sibling::text()"/>
578
+ <xsl:variable name="initial-content">
579
+ <xsl:apply-templates select="$initial"/>
580
+ </xsl:variable>
581
+ <!-- XSLT 1.0: RTF is just a string if not converted to node set -->
582
+ <xsl:if test="not($initial-content = '')">
583
+ <p>
584
+ <xsl:copy-of select="$initial-content"/>
585
+ </p>
586
+ </xsl:if>
587
+ <!-- for each display: the display itself, then trailing content -->
588
+ <xsl:for-each select="$displays">
589
+ <xsl:apply-templates select="."/>
590
+ <xsl:variable name="rightward" select="following-sibling::*|following-sibling::text()"/>
591
+ <xsl:variable name="next-display" select="following-sibling::*[self::ul or self::ol or self::dl or self::md[mrow] or self::cd][1]"/>
592
+ <xsl:choose>
593
+ <xsl:when test="$next-display">
594
+ <xsl:variable name="leftward" select="$next-display/preceding-sibling::*|$next-display/preceding-sibling::text()"/>
595
+ <!-- device below forms set intersection -->
596
+ <xsl:variable name="common" select="$rightward[count(. | $leftward) = count($leftward)]"/>
597
+ <xsl:variable name="common-content">
598
+ <xsl:apply-templates select="$common"/>
599
+ </xsl:variable>
600
+ <xsl:if test="not($common-content = '')">
601
+ <p>
602
+ <!-- interstitial content arising from an authored -->
603
+ <!-- "intertext" is marked, as in the HTML -->
604
+ <!-- conversion, for styling purposes -->
605
+ <xsl:if test="$common[self::pi:intertext]">
606
+ <xsl:attribute name="class">
607
+ <xsl:text>intertext</xsl:text>
608
+ </xsl:attribute>
609
+ </xsl:if>
610
+ <xsl:copy-of select="$common-content"/>
611
+ </p>
612
+ </xsl:if>
613
+ </xsl:when>
614
+ <xsl:otherwise>
615
+ <!-- finish the trailing content, if nonempty -->
616
+ <xsl:variable name="common-content">
617
+ <xsl:apply-templates select="$rightward"/>
618
+ </xsl:variable>
619
+ <xsl:if test="not($common-content = '')">
620
+ <p>
621
+ <xsl:copy-of select="$common-content"/>
622
+ </p>
623
+ </xsl:if>
624
+ </xsl:otherwise>
625
+ </xsl:choose>
626
+ </xsl:for-each>
627
+ </xsl:template>
628
+
528
629
  <!-- Images get wrapped in a div with @class="fragment" if they are -->
529
630
  <!-- paused -->
530
631
  <xsl:template match="image[not(ancestor::sidebyside) and (@pause='yes')]">
@@ -1299,4 +1299,34 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
1299
1299
  </xsl:choose>
1300
1300
  </xsl:template>
1301
1301
 
1302
+ <!-- Escape arbitrary text for a single-quoted CSS string: -->
1303
+ <!-- backslash and apostrophe by a backslash, and a less-than by -->
1304
+ <!-- its code point (with delimiting space). The last means the -->
1305
+ <!-- text can never terminate an enclosing HTML "style" element -->
1306
+ <!-- prematurely, since an HTML parser ends such an element at a -->
1307
+ <!-- literal "</style" no matter the surrounding CSS syntax. -->
1308
+ <xsl:template name="css-string-escape">
1309
+ <xsl:param name="text"/>
1310
+ <xsl:if test="not($text = '')">
1311
+ <xsl:variable name="first" select="substring($text, 1, 1)"/>
1312
+ <xsl:choose>
1313
+ <xsl:when test="$first = '\'">
1314
+ <xsl:text>\\</xsl:text>
1315
+ </xsl:when>
1316
+ <xsl:when test='$first = "&apos;"'>
1317
+ <xsl:text>\&apos;</xsl:text>
1318
+ </xsl:when>
1319
+ <xsl:when test="$first = '&lt;'">
1320
+ <xsl:text>\3c </xsl:text>
1321
+ </xsl:when>
1322
+ <xsl:otherwise>
1323
+ <xsl:value-of select="$first"/>
1324
+ </xsl:otherwise>
1325
+ </xsl:choose>
1326
+ <xsl:call-template name="css-string-escape">
1327
+ <xsl:with-param name="text" select="substring($text, 2)"/>
1328
+ </xsl:call-template>
1329
+ </xsl:if>
1330
+ </xsl:template>
1331
+
1302
1332
  </xsl:stylesheet>