From 947a5fa2bf1388eeb13f84817f5c664b3a7da644 Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Sun, 12 Apr 2026 11:53:55 -0700 Subject: [PATCH 1/7] XSL: add activecode and codelense to qrcode generation --- xsl/extract-qrcode.xsl | 6 +++++- xsl/pretext-assembly.xsl | 6 ++++++ xsl/pretext-common.xsl | 8 ++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/xsl/extract-qrcode.xsl b/xsl/extract-qrcode.xsl index 39d4c4f0c..9ccf6fa49 100644 --- a/xsl/extract-qrcode.xsl +++ b/xsl/extract-qrcode.xsl @@ -74,7 +74,11 @@ along with PreTeXt. If not, see . - + diff --git a/xsl/pretext-assembly.xsl b/xsl/pretext-assembly.xsl index 32b742621..37b76b8a5 100644 --- a/xsl/pretext-assembly.xsl +++ b/xsl/pretext-assembly.xsl @@ -4023,6 +4023,9 @@ along with PreTeXt. If not, see . + + + @@ -4041,6 +4044,9 @@ along with PreTeXt. If not, see . + + + diff --git a/xsl/pretext-common.xsl b/xsl/pretext-common.xsl index 5b12bac22..b9f2879b9 100644 --- a/xsl/pretext-common.xsl +++ b/xsl/pretext-common.xsl @@ -2455,6 +2455,14 @@ Book (with parts), "section" at level 3 + + + + + # + + + From 37693f379ad62f42ff28705cabcdc376587932e1 Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Sun, 12 Apr 2026 11:55:05 -0700 Subject: [PATCH 2/7] Script: qrcode URL falls back on context-url if no standalone-url --- pretext/lib/pretext.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pretext/lib/pretext.py b/pretext/lib/pretext.py index 39e92443e..63badd210 100644 --- a/pretext/lib/pretext.py +++ b/pretext/lib/pretext.py @@ -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") From d071db4137b818ea4da651e91197a38b97286aba Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Sun, 12 Apr 2026 12:11:40 -0700 Subject: [PATCH 3/7] Publisher: add program/@static-qrcodes pub attribute --- xsl/publisher-variables.xsl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/xsl/publisher-variables.xsl b/xsl/publisher-variables.xsl index 2e77ae3dd..49ab7df7a 100644 --- a/xsl/publisher-variables.xsl +++ b/xsl/publisher-variables.xsl @@ -156,6 +156,12 @@ along with PreTeXt. If not, see . + + + + + + @@ -3347,6 +3353,9 @@ along with PreTeXt. If not, see . + + + From b0f5b535892a9f6c391ca73f1fb683c6988616db Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Sun, 12 Apr 2026 12:06:58 -0700 Subject: [PATCH 4/7] Assembly: add static representation with QRCode for activecode and codelens --- xsl/pretext-assembly.xsl | 46 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/xsl/pretext-assembly.xsl b/xsl/pretext-assembly.xsl index 37b76b8a5..34d78c41f 100644 --- a/xsl/pretext-assembly.xsl +++ b/xsl/pretext-assembly.xsl @@ -2326,6 +2326,10 @@ along with PreTeXt. If not, see . + + + + @@ -3755,6 +3759,48 @@ along with PreTeXt. If not, see . + + + + + + + + + + + + + + + + + +

+ + + +

+
+ + + qrcode/ + + .png + + +
+
+
+
+ + + + + +
+
+ From d418c1e935f8731d167f1c34413ae6a8434d2705 Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Sun, 12 Apr 2026 12:07:55 -0700 Subject: [PATCH 5/7] Runestone: use representations pathway for rendering static interactive programs --- xsl/pretext-runestone-static.xsl | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/xsl/pretext-runestone-static.xsl b/xsl/pretext-runestone-static.xsl index 0f0dfa297..87b5177a7 100644 --- a/xsl/pretext-runestone-static.xsl +++ b/xsl/pretext-runestone-static.xsl @@ -1339,17 +1339,10 @@ along with PreTeXt. If not, see . - - - - - - - - - - - + + + + From 988914a5580b42db21e0e35e2832f1b5e3309254 Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Sun, 12 Apr 2026 12:12:16 -0700 Subject: [PATCH 6/7] Guide: document program/@static-qrcodes pub var --- doc/guide/author/topics.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/guide/author/topics.xml b/doc/guide/author/topics.xml index 4185f6e20..01f90d49b 100644 --- a/doc/guide/author/topics.xml +++ b/doc/guide/author/topics.xml @@ -3598,7 +3598,7 @@ Interactive Programs, CodeLens -

CodeLens 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 HTML is hosted on a Runestone server (). This may also be accomplished in browser when hosted on any old generic web server. The catch is that for a generic server a publisher must generate trace data in advance, typically with the PreTeXt-CLI (). Place the interactive attribute on a program element with the value codelens to elect this behavior (no is the default value). Also, be sure to specify a language from the supported languages: Python, Java, C, and C++. Consult 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 program should have an xml:id that will be used as a unique identifier for the generated trace file needed by the codelens.

+

CodeLens 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 HTML is hosted on a Runestone server (). This may also be accomplished in browser when hosted on any old generic web server. The catch is that for a generic server a publisher must generate trace data in advance, typically with the PreTeXt-CLI (). Place the interactive attribute on a program element with the value codelens to elect this behavior (no is the default value). Also, be sure to specify a language from the supported languages: Python, Java, C, and C++. Consult 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 program should have an xml:id that will be used as a unique identifier for the generated trace file needed by the codelens.

Sometimes, there is uninteresting setup to get through before the portion of the program the author wants to illustrate. The author can use starting-step 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 starting-step is a Step 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.

@@ -3617,7 +3617,9 @@

ActiveCode 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 in browser on any old generic web server, while others must be on a Runestone server () where a Jobe Server is running to support the execution.

-

Place the interactive attribute on a program element with the value activecode to elect this behavior (no is the default value). Also, be sure to specify a language from the supported languages. Consult 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.

+

Place the interactive attribute on a program element with the value activecode to elect this behavior (no is the default value). Also, be sure to specify a language from the supported languages. Consult 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. If a base URL is configured (see ), the static listing may also include a QR code and an In Context link to the interactive HTML version. You can disable these QR codes with the publisher variable common/program/@static-qrcodes="no".

Labels and XML IDs From ab0a98622848118c92918c94eb30147f6e8288d2 Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Sun, 12 Apr 2026 12:19:36 -0700 Subject: [PATCH 7/7] Publication schema: add common/program/@static-qrcodes --- schema/publication-schema.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/schema/publication-schema.xml b/schema/publication-schema.xml index ee81b6440..16e712d1b 100644 --- a/schema/publication-schema.xml +++ b/schema/publication-schema.xml @@ -157,6 +157,9 @@ element qrcode { attribute image { text } }? & + element program { + attribute static-qucodes { text }? + }? & element journal { attribute name {text} }? &