Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions doc/guide/author/topics.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3598,7 +3598,7 @@
<subsection xml:id="interactive-program-codelens">
<title>Interactive Programs, CodeLens</title>

<p><term>CodeLens</term> is an interactive version of a computer program, which can be visualized by stepping through the code one statement at a time, watching output, variables, and other data structures change. So it is similar to a debugger, except the reader does not set breakpoints or modify program data on-the-fly. This is possible automatically for several different languages when your <init>HTML</init> is hosted on a Runestone server (<xref ref="runestone"/>). This may also be accomplished <q>in browser</q> when hosted on any old generic web server. The catch is that for a generic server a publisher must generate <term>trace data</term> in advance, typically with the PreTeXt-CLI (<xref ref="processing-CLI"/>). Place the <tag>interactive</tag> attribute on a <tag>program</tag> element with the value <c>codelens</c> to elect this behavior (<c>no</c> is the default value). Also, be sure to specify a language from the supported languages: Python, Java, C, and C++. Consult <xref ref="table-program-interactive"/> below for a summary of various combinations. When an output format does not support an interactive CodeLens instance, the fallback is a static program listing. The <tag>program</tag> should have an <attr>xml:id</attr> that will be used as a unique identifier for the generated trace file needed by the codelens.</p>
<p><term>CodeLens</term> is an interactive version of a computer program, which can be visualized by stepping through the code one statement at a time, watching output, variables, and other data structures change. So it is similar to a debugger, except the reader does not set breakpoints or modify program data on-the-fly. This is possible automatically for several different languages when your <init>HTML</init> is hosted on a Runestone server (<xref ref="runestone"/>). This may also be accomplished <q>in browser</q> when hosted on any old generic web server. The catch is that for a generic server a publisher must generate <term>trace data</term> in advance, typically with the PreTeXt-CLI (<xref ref="processing-CLI"/>). Place the <tag>interactive</tag> attribute on a <tag>program</tag> element with the value <c>codelens</c> to elect this behavior (<c>no</c> is the default value). Also, be sure to specify a language from the supported languages: Python, Java, C, and C++. Consult <xref ref="table-program-interactive"/> below for a summary of various combinations. When an output format does not support an interactive CodeLens instance, the fallback is a static program listing, possibly with a link to the interactive version. The <tag>program</tag> should have an <attr>xml:id</attr> that will be used as a unique identifier for the generated trace file needed by the codelens.</p>

<p>Sometimes, there is uninteresting setup to get through before the portion of the program the author wants to illustrate. The author can use <attr>starting-step</attr> to specify the instruction number that the interactive should start at. Code before that will be fast-forwarded through and execution will begin at the indicted step. Note that <attr>starting-step</attr> is a <q>Step</q> number in the execution sequence, not a line number in the source code. You may have to run the Codelens once to find the right step to start at.</p>

Expand All @@ -3617,7 +3617,9 @@

<p><term>ActiveCode</term> is an interactive environment where a reader may work on code through repeated edit-compile-test cycles. Code can be provided by an author as a complete program to be modified, a partial program to be completed, or nothing at all. One good example is that maybe header files, import statement, and similar are provided, and a skeleton of a main entry-point procedure is also provided. Then a reader can concentrate on the more conceptual parts of the programming. Some languages will be executable <q>in browser</q> on any old generic web server, while others must be on a Runestone server (<xref ref="runestone"/>) where a <url href="https://github.com/trampgeek/jobe" visual="github.com/trampgeek/jobe">Jobe Server</url> is running to support the execution.</p>

<p>Place the <attr>interactive</attr> attribute on a <tag>program</tag> element with the value <c>activecode</c> to elect this behavior (<c>no</c> is the default value). Also, be sure to specify a language from the supported languages. Consult <xref ref="table-program-interactive"/> below for a summary of various combinations. When an output format does not support an interactive ActiveCode instance, the fallback is a static program listing.</p>
<p>Place the <attr>interactive</attr> attribute on a <tag>program</tag> element with the value <c>activecode</c> to elect this behavior (<c>no</c> is the default value). Also, be sure to specify a language from the supported languages. Consult <xref ref="table-program-interactive"/> below for a summary of various combinations.</p>

<p>When an output format does not support an interactive ActiveCode instance, the fallback is a static program listing. If a base <init>URL</init> is configured (see <xref ref="online-baseurl"/>), the static listing may also include a QR code and an <q>In Context</q> link to the interactive HTML version. You can disable these QR codes with the publisher variable <c>common/program/@static-qrcodes="no"</c>.</p>

<warning>
<title>Labels and XML IDs</title>
Expand Down
11 changes: 9 additions & 2 deletions pretext/lib/pretext.py
Original file line number Diff line number Diff line change
Expand Up @@ -2617,13 +2617,20 @@ def qrcode(xml_source, pub_file, stringparams, xmlid_root, dest_dir):
# Extraction writes sidecar XML files (one per element) into dest_dir
# via exsl:document, each containing standalone and in-context URLs.
xsltproc(extraction_xslt, xml_source, None, dest_dir, stringparams)
# Read sidecar XML files to get URLs for QR code generation
# Read sidecar XML files to get URLs for QR code generation.
# Interactive programs intentionally leave standalone URLs empty,
# so fall back to the in-context page URL in that case.
pi_ns = {'pi': 'http://pretextbook.org/2020/pretext/internal'}
url_files = sorted(glob.glob(os.path.join(dest_dir, "*-url.xml")))
for url_file in url_files:
tree = ET.parse(url_file)
url = tree.find('pi:standalone-url', pi_ns).text
# Derive visible-id from filename: {id}-url.xml
if not url:
url = tree.find('pi:context-url', pi_ns).text
if not url:
log.info('skipping QR code creation for {} because no URL was provided'.format(url_file))
continue
# Derive internal id from filename: {id}-url.xml
basename = os.path.splitext(os.path.basename(url_file))[0]
the_id = basename.rsplit('-url', 1)[0]
path = os.path.join(dest_dir, the_id + ".png")
Expand Down
3 changes: 3 additions & 0 deletions schema/publication-schema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@
element qrcode {
attribute image { text }
}? &amp;
element program {
attribute static-qucodes { text }?
}? &amp;
element journal {
attribute name {text}
}? &amp;
Expand Down
6 changes: 5 additions & 1 deletion xsl/extract-qrcode.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,11 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
<xsl:variable name="chunk-level" select="$html-chunk-level"/>
<xsl:variable name="file-extension" select="'.html'"/>

<xsl:template match="audio[@source|@href]|video[@source|@href|@youtube|@youtubeplaylist|@vimeo]|interactive" mode="extraction">
<xsl:template match="audio[@source|@href]
| video[@source|@href|@youtube|@youtubeplaylist|@vimeo]
| interactive
| program[@interactive = 'activecode' or @interactive = 'codelens']"
mode="extraction">
<!-- Sidecar XML file with pre-computed URLs for use -->
<!-- by pretext-assembly.xsl when building static -->
<!-- representations, and by the Python script when -->
Expand Down
52 changes: 52 additions & 0 deletions xsl/pretext-assembly.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -2326,6 +2326,10 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
<xsl:value-of select="@assembly-id"/>
</xsl:template>

<xsl:template match="program[@interactive = 'activecode' or @interactive = 'codelens']" mode="assembly-id">
<xsl:value-of select="@assembly-id"/>
</xsl:template>

<xsl:template match="datafile" mode="assembly-id">
<xsl:value-of select="@assembly-id"/>
</xsl:template>
Expand Down Expand Up @@ -3755,6 +3759,48 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
</xsl:choose>
</xsl:template>

<xsl:template match="program[@interactive = 'activecode' or @interactive = 'codelens']" mode="representations">
<xsl:choose>
<xsl:when test="$exercise-style = 'static'">
<xsl:copy>
<xsl:apply-templates select="node()|@*" mode="representations"/>
</xsl:copy>
<xsl:if test="$b-program-static-qrcodes and not($b-extracting)">
<xsl:variable name="url-file-rtf">
<xsl:copy-of select="document(concat($generated-directory-source, 'qrcode/', @assembly-id, '-url.xml'), $original)"/>
</xsl:variable>
<xsl:variable name="url-file" select="exsl:node-set($url-file-rtf)"/>
<xsl:variable name="context-url">
<xsl:value-of select="$url-file/pi:qrcode-urls/pi:context-url"/>
</xsl:variable>
<xsl:if test="not($context-url = '')">
<sidebyside margins="0%" widths="70% 25%" valign="middle" halign="center">
<paragraphs>
<p pi:indent="no">
<url href="{$context-url}" visual="">
<pi:localize string-id="incontext"/>
</url>
</p>
</paragraphs>
<image>
<xsl:attribute name="pi:generated">
<xsl:text>qrcode/</xsl:text>
<xsl:apply-templates select="." mode="assembly-id"/>
<xsl:text>.png</xsl:text>
</xsl:attribute>
</image>
</sidebyside>
</xsl:if>
</xsl:if>
</xsl:when>
<xsl:when test="($exercise-style = 'dynamic') or ($exercise-style = 'pg-problems')">
<xsl:copy>
<xsl:apply-templates select="node()|@*" mode="representations"/>
</xsl:copy>
</xsl:when>
</xsl:choose>
</xsl:template>

<xsl:template match="datafile|query" mode="representations">
<xsl:choose>
<!-- make a static version, in a PreTeXt style -->
Expand Down Expand Up @@ -4023,6 +4069,9 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
<xsl:template match="audio|video" mode="embed-iframe-url"/>
<xsl:template match="interactive[@desmos|@geogebra|@calcplot3d|@circuitjs|@iframe]" mode="embed-iframe-url"/>

<!-- Programs should not get embed urls in sidecar files -->
<xsl:template match="program[@interactive = 'activecode' or @interactive = 'codelens']" mode="embed-iframe-url"/>


<!-- Static URL's -->
<!-- Predictable and/or stable URLs for versions -->
Expand All @@ -4041,6 +4090,9 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
<xsl:apply-templates select="." mode="standalone-filename" />
</xsl:template>

<!-- Programs should not get standalone urls in sidecar files -->
<xsl:template match="program[@interactive = 'activecode' or @interactive = 'codelens']" mode="static-url"/>

<!-- Natural override for YouTube videos -->
<!-- Better - standalone page, with "View on You Tube" -->

Expand Down
8 changes: 8 additions & 0 deletions xsl/pretext-common.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -2455,6 +2455,14 @@ Book (with parts), "section" at level 3
</xsl:if>
</xsl:template>

<xsl:template match="program[@interactive = 'activecode' or @interactive = 'codelens']" mode="context-url">
<xsl:if test="$b-has-baseurl">
<xsl:value-of select="$baseurl"/>
<xsl:apply-templates select="." mode="containing-filename"/>
<xsl:text>#</xsl:text>
<xsl:apply-templates select="." mode="runestone-id"/>
</xsl:if>
</xsl:template>

<!-- ###### -->
<!-- Titles -->
Expand Down
15 changes: 4 additions & 11 deletions xsl/pretext-runestone-static.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -1339,17 +1339,10 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
<statement>
<!-- duplicate the authored prompt/statement -->
<xsl:copy-of select="statement/node()"/>
<!-- Bring up the program as part of the problem statement and -->
<!-- also neuter any @interactive indication. This was not -->
<!-- tagged as a coding exercise without a "program" outside -->
<!-- the "statement", but we are careful about not making an -->
<!-- empty "program" where there is none. -->
<xsl:if test="program">
<xsl:element name="program">
<xsl:copy-of select="program/@*[not(name() = 'interactive')]"/>
<xsl:copy-of select="program/node()"/>
</xsl:element>
</xsl:if>
<!-- Bring up the program as part of the problem statement. -->
<!-- Route this through representations so static builds -->
<!-- can add the same QR/link treatment as other objects. -->
<xsl:apply-templates select="program" mode="representations"/>
</statement>
<xsl:copy-of select="hint"/>
<xsl:copy-of select="answer"/>
Expand Down
9 changes: 9 additions & 0 deletions xsl/publisher-variables.xsl
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,12 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
<xsl:apply-templates select="$publisher-attribute-options/common/qrcode/pi:pub-attribute[@name='image']" mode="set-pubfile-variable"/>
</xsl:variable>

<!-- Should QR codes be built for interactive programs in static output -->
<xsl:variable name="program-static-qrcodes">
<xsl:apply-templates select="$publisher-attribute-options/common/program/pi:pub-attribute[@name='static-qrcodes']" mode="set-pubfile-variable"/>
</xsl:variable>
<xsl:variable name="b-program-static-qrcodes" select="$program-static-qrcodes = 'yes'"/>

<!-- Em dash Width -->

<xsl:variable name="emdash-space">
Expand Down Expand Up @@ -3347,6 +3353,9 @@ along with PreTeXt. If not, see <http://www.gnu.org/licenses/>.
<qrcode>
<pi:pub-attribute name="image" default="" freeform="yes"/>
</qrcode>
<program>
<pi:pub-attribute name="static-qrcodes" default="yes" options="no"/>
</program>
<mermaid>
<pi:pub-attribute name="theme" default="default" options="dark forest light"/>
<pi:pub-attribute name="layout-engine" default="dagre" options="elk"/>
Expand Down