From 55f59d0df0e32e6f24208c52c816552534571b37 Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Fri, 22 Aug 2025 16:59:17 -0700 Subject: [PATCH 01/16] QRCodes: extraction generates url sidecar files --- xsl/entities.ent | 3 ++ xsl/extract-qrcode.xsl | 68 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/xsl/entities.ent b/xsl/entities.ent index a22791eb0e..cb4b8e6ef9 100644 --- a/xsl/entities.ent +++ b/xsl/entities.ent @@ -145,3 +145,6 @@ + + + diff --git a/xsl/extract-qrcode.xsl b/xsl/extract-qrcode.xsl index b5aef2a47c..1a41d4aca0 100644 --- a/xsl/extract-qrcode.xsl +++ b/xsl/extract-qrcode.xsl @@ -19,6 +19,11 @@ You should have received a copy of the GNU General Public License along with MathBook XML. If not, see . *********************************************************************--> + + %entities; +]> + @@ -36,6 +41,9 @@ along with MathBook XML. If not, see . + + + @@ -46,18 +54,70 @@ along with MathBook XML. If not, see . - + - - + + + + + + + + + PTX:INFO: Writing qrcode-urls.txt + + + + PTX:ERROR: Base URL must be specified to generate QR codes + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From e9aece33acb94ea9feab32929b993e928064360e Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Fri, 22 Aug 2025 17:07:21 -0700 Subject: [PATCH 02/16] Assembly: rely on sidecar file for qrcode static urls --- xsl/pretext-assembly.xsl | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/xsl/pretext-assembly.xsl b/xsl/pretext-assembly.xsl index 6d75eb9d03..5304591a5f 100644 --- a/xsl/pretext-assembly.xsl +++ b/xsl/pretext-assembly.xsl @@ -3773,11 +3773,11 @@ along with PreTeXt. If not, see . - - - + + + @@ -4135,4 +4135,9 @@ along with PreTeXt. If not, see . + + + + + From 98a707acba09ae730917493a681bbd188ad3978e Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Fri, 22 Aug 2025 17:00:02 -0700 Subject: [PATCH 03/16] Publisher variables: add common/program/@static-qr-codes --- xsl/publisher-variables.xsl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/xsl/publisher-variables.xsl b/xsl/publisher-variables.xsl index d4bd27e1e8..320bd262f0 100644 --- a/xsl/publisher-variables.xsl +++ b/xsl/publisher-variables.xsl @@ -156,6 +156,12 @@ along with PreTeXt. If not, see . + + + + + + @@ -3317,6 +3323,9 @@ along with PreTeXt. If not, see . + + + From d8895e4f10af0a7b0377637ca7d03c407d6804dd Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Fri, 22 Aug 2025 16:55:48 -0700 Subject: [PATCH 04/16] Localization: add program-interactive-available --- xsl/localizations/af-ZA.xml | 1 + xsl/localizations/bg-BG.xml | 1 + xsl/localizations/ca-ES.xml | 1 + xsl/localizations/cs-CZ.xml | 1 + xsl/localizations/de-DE.xml | 1 + xsl/localizations/en-US.xml | 1 + xsl/localizations/es-ES.xml | 1 + xsl/localizations/fi-FI.xml | 1 + xsl/localizations/fr-CA.xml | 1 + xsl/localizations/fr-FR.xml | 1 + xsl/localizations/hu-HU.xml | 1 + xsl/localizations/it-IT.xml | 1 + xsl/localizations/ku-CKB.xml | 1 + xsl/localizations/nl-NL.xml | 4 ++-- xsl/localizations/pt-BR.xml | 1 + xsl/localizations/pt-PT.xml | 1 + xsl/localizations/zh-HANS.xml | 1 + 17 files changed, 18 insertions(+), 2 deletions(-) diff --git a/xsl/localizations/af-ZA.xml b/xsl/localizations/af-ZA.xml index fc58f1bb23..24e247a6f3 100644 --- a/xsl/localizations/af-ZA.xml +++ b/xsl/localizations/af-ZA.xml @@ -200,6 +200,7 @@ along with PreTeXt. If not, see . ActiveCode CodeLens + diff --git a/xsl/localizations/bg-BG.xml b/xsl/localizations/bg-BG.xml index 298a781de2..3c8ce3fdbd 100644 --- a/xsl/localizations/bg-BG.xml +++ b/xsl/localizations/bg-BG.xml @@ -218,6 +218,7 @@ along with PreTeXt. If not, see . ActiveCode CodeLens + diff --git a/xsl/localizations/ca-ES.xml b/xsl/localizations/ca-ES.xml index 74dd313e63..2a21727257 100644 --- a/xsl/localizations/ca-ES.xml +++ b/xsl/localizations/ca-ES.xml @@ -204,6 +204,7 @@ along with PreTeXt. If not, see . ActiveCode CodeLens + diff --git a/xsl/localizations/cs-CZ.xml b/xsl/localizations/cs-CZ.xml index caae4c5305..505fcc1cb8 100644 --- a/xsl/localizations/cs-CZ.xml +++ b/xsl/localizations/cs-CZ.xml @@ -200,6 +200,7 @@ along with PreTeXt. If not, see . Otázka ActiveCode CodeLens + diff --git a/xsl/localizations/de-DE.xml b/xsl/localizations/de-DE.xml index c29b4485f5..f05b52101c 100644 --- a/xsl/localizations/de-DE.xml +++ b/xsl/localizations/de-DE.xml @@ -203,6 +203,7 @@ along with PreTeXt. If not, see . ActiveCode CodeLens + diff --git a/xsl/localizations/en-US.xml b/xsl/localizations/en-US.xml index 19bcff6567..1e84f67926 100644 --- a/xsl/localizations/en-US.xml +++ b/xsl/localizations/en-US.xml @@ -266,6 +266,7 @@ along with PreTeXt. If not, see . ActiveCode CodeLens + Interactive program diff --git a/xsl/localizations/es-ES.xml b/xsl/localizations/es-ES.xml index 2107f6de4e..e3e5237ed5 100644 --- a/xsl/localizations/es-ES.xml +++ b/xsl/localizations/es-ES.xml @@ -206,6 +206,7 @@ along with PreTeXt. If not, see . Consulta ActiveCode CodeLens + diff --git a/xsl/localizations/fi-FI.xml b/xsl/localizations/fi-FI.xml index d97c514268..e81d0b6b20 100644 --- a/xsl/localizations/fi-FI.xml +++ b/xsl/localizations/fi-FI.xml @@ -210,6 +210,7 @@ along with PreTeXt. If not, see . ActiveCode CodeLens + diff --git a/xsl/localizations/fr-CA.xml b/xsl/localizations/fr-CA.xml index a12a845632..24507ff697 100644 --- a/xsl/localizations/fr-CA.xml +++ b/xsl/localizations/fr-CA.xml @@ -201,6 +201,7 @@ along with PreTeXt. If not, see . Requête ActiveCode CodeLens + diff --git a/xsl/localizations/fr-FR.xml b/xsl/localizations/fr-FR.xml index 78b834ed1a..9deecfdbcc 100644 --- a/xsl/localizations/fr-FR.xml +++ b/xsl/localizations/fr-FR.xml @@ -198,6 +198,7 @@ along with PreTeXt. If not, see . ActiveCode CodeLens + diff --git a/xsl/localizations/hu-HU.xml b/xsl/localizations/hu-HU.xml index 6c7edba42c..969a275931 100644 --- a/xsl/localizations/hu-HU.xml +++ b/xsl/localizations/hu-HU.xml @@ -200,6 +200,7 @@ along with PreTeXt. If not, see . ActiveCode CodeLens + diff --git a/xsl/localizations/it-IT.xml b/xsl/localizations/it-IT.xml index c4def4e6f0..a7e52dedd4 100644 --- a/xsl/localizations/it-IT.xml +++ b/xsl/localizations/it-IT.xml @@ -194,6 +194,7 @@ along with PreTeXt. If not, see . Programma ActiveCode CodeLens + diff --git a/xsl/localizations/ku-CKB.xml b/xsl/localizations/ku-CKB.xml index a8d0f6b088..5d251af9d2 100644 --- a/xsl/localizations/ku-CKB.xml +++ b/xsl/localizations/ku-CKB.xml @@ -221,6 +221,7 @@ along with PreTeXt. If not, see . کۆد-چالاکردن CodeLens + diff --git a/xsl/localizations/nl-NL.xml b/xsl/localizations/nl-NL.xml index 62c7e23bb3..a51c773ae8 100644 --- a/xsl/localizations/nl-NL.xml +++ b/xsl/localizations/nl-NL.xml @@ -231,8 +231,8 @@ along with PreTeXt. If not, see . + CodeLens --> + diff --git a/xsl/localizations/pt-BR.xml b/xsl/localizations/pt-BR.xml index c8716f7d46..e7f7245acb 100644 --- a/xsl/localizations/pt-BR.xml +++ b/xsl/localizations/pt-BR.xml @@ -201,6 +201,7 @@ along with PreTeXt. If not, see . Programa ActiveCode CodeLens + diff --git a/xsl/localizations/pt-PT.xml b/xsl/localizations/pt-PT.xml index 786351cb73..a427b4d426 100644 --- a/xsl/localizations/pt-PT.xml +++ b/xsl/localizations/pt-PT.xml @@ -209,6 +209,7 @@ along with PreTeXt. If not, see . ActiveCode CodeLens + diff --git a/xsl/localizations/zh-HANS.xml b/xsl/localizations/zh-HANS.xml index 527d8494c6..92d1cde28b 100644 --- a/xsl/localizations/zh-HANS.xml +++ b/xsl/localizations/zh-HANS.xml @@ -229,6 +229,7 @@ along with PreTeXt. If not, see . ActiveCode CodeLens + From 4fe2acba7885d022e02cced1b27cf8fdcf0cc757 Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Fri, 22 Aug 2025 17:08:38 -0700 Subject: [PATCH 05/16] Assembly: add qrcodes for static representations of interactive programs --- xsl/pretext-assembly.xsl | 56 ++++++++++++++++++++++++++++++++ xsl/pretext-runestone-static.xsl | 3 ++ 2 files changed, 59 insertions(+) diff --git a/xsl/pretext-assembly.xsl b/xsl/pretext-assembly.xsl index 5304591a5f..70bb6178f2 100644 --- a/xsl/pretext-assembly.xsl +++ b/xsl/pretext-assembly.xsl @@ -2323,6 +2323,10 @@ along with PreTeXt. If not, see . + + + + @@ -4089,6 +4093,12 @@ along with PreTeXt. If not, see . + + + + + + @@ -4140,4 +4150,50 @@ along with PreTeXt. If not, see . + + + + + + + + + + + + + + + +

+ + program-interactive-available + +

+

+ + + + +

+
+ + + qrcode/ + + .png + + +
+
+
+ + + + + + +
+
+ diff --git a/xsl/pretext-runestone-static.xsl b/xsl/pretext-runestone-static.xsl index 0f0dfa297e..64817ff04d 100644 --- a/xsl/pretext-runestone-static.xsl +++ b/xsl/pretext-runestone-static.xsl @@ -1350,6 +1350,9 @@ along with PreTeXt. If not, see . + + + From bcb0b8240d42e3814ac0dc043b72acafac877633 Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Fri, 22 Aug 2025 21:12:06 -0700 Subject: [PATCH 06/16] Guide: note about ActiveCode/Codelens QR codes --- 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 db6d882be5..f3e400c0cf 100644 --- a/doc/guide/author/topics.xml +++ b/doc/guide/author/topics.xml @@ -3594,7 +3594,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 (see for how to configure the links). 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.

@@ -3610,7 +3610,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. The static listing is possibly supplemented with a link and QR code to access an HTML version. To get these links, you must specify a base URL (see ). If you have a base URL and want to disable the QR codes, you can set the static-qrcodes attribute to no "no" in the publisher variable common/program.

Labels and XML IDs From 7a15cb4c16eed6fea62506eba936e6cd314f72f7 Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Tue, 6 May 2025 17:12:00 -0700 Subject: [PATCH 07/16] Script: refactor setting runestone stringparams --- pretext/lib/pretext.py | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/pretext/lib/pretext.py b/pretext/lib/pretext.py index efe28259a2..9d556451cc 100644 --- a/pretext/lib/pretext.py +++ b/pretext/lib/pretext.py @@ -4397,6 +4397,12 @@ def _parse_runestone_services(et): return (rs_js, rs_css, rs_cdn_url, rs_version) +# Update stringparams with Runestone Services information +def _set_runestone_stringparams(stringparams, rs_js, rs_css, rs_version): + stringparams["rs-js"] = rs_js + stringparams["rs-css"] = rs_css + stringparams["rs-version"] = rs_version + # A helper function to query the latest Runestone # Services file, while failing gracefully @@ -4442,15 +4448,8 @@ def _runestone_services(stringparams, ext_rs_methods): # Developer is responsible for placement of the right files in _static # ** Simply return early with stock values (or None) ** if "debug.rs.dev" in stringparams: - rs_js = "prefix-runtime.bundle.js:prefix-runtime-libs.bundle.js:prefix-runestone.bundle.js" - rs_css = "prefix-runtime-libs.css:prefix-runestone.css" - rs_cdn_url = None - rs_version = "dev" - services_xml = None - # Return, plus side-effect - stringparams["rs-js"] = rs_js - stringparams["rs-css"] = rs_css - stringparams["rs-version"] = rs_version + rs_js, rs_css, rs_cdn_url, rs_version, services_xml = _runestone_debug_service_info() + _set_runestone_stringparams(stringparams, rs_js, rs_css, rs_version) return (rs_js, rs_css, rs_cdn_url, rs_version, services_xml) # Otherwise, we have a URL pointing to the Runestone server/CDN @@ -4477,11 +4476,17 @@ def _runestone_services(stringparams, ext_rs_methods): rs_js, rs_css, rs_cdn_url, rs_version = _parse_runestone_services(services) # Return, plus side-effect - stringparams["rs-js"] = rs_js - stringparams["rs-css"] = rs_css - stringparams["rs-version"] = rs_version + _set_runestone_stringparams(stringparams, rs_js, rs_css, rs_version) return (rs_js, rs_css, rs_cdn_url, rs_version, services_xml) +def _runestone_debug_service_info(): + """Return hardcoded values used for debugging Runestone Services (debug.rs.dev)""" + rs_js = "prefix-runtime.bundle.js:prefix-runtime-libs.bundle.js:prefix-runestone.bundle.js" + rs_css = "prefix-runtime-libs.css:prefix-runestone.css" + rs_cdn_url = None + rs_version = "dev" + services_xml = None + return (rs_js, rs_css, rs_cdn_url, rs_version, services_xml) def _cdn_runestone_services(stringparams, ext_rs_methods): """Version of _runestone_services function to query the Runestone Services file from the PreTeXt html-static CDN""" From 453b65e57571da633ef9341f00fd5f34df689d2c Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Tue, 6 May 2025 17:19:04 -0700 Subject: [PATCH 08/16] Script: add function to get RS services data from existing build --- pretext/lib/pretext.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pretext/lib/pretext.py b/pretext/lib/pretext.py index 9d556451cc..75552bb0b6 100644 --- a/pretext/lib/pretext.py +++ b/pretext/lib/pretext.py @@ -4591,6 +4591,21 @@ def query_runestone_services(services_url): return services_response.text +def query_existing_runestone_services(dest_dir, stringparams): + '''Attempt to get Runestone service data from existing + Runestone Services file in _static directory. + Returns a tuple of the JS, CSS, CDN URL and version or None''' + services_record_files = os.path.join(dest_dir, "_static", "_runestone-services.xml") + + if os.path.exists(services_record_files): + with open(services_record_files, 'r') as f: + services_xml = f.read() + services = ET.fromstring(services_xml) + return _parse_runestone_services(services) + else: + msg = "query_existing_runestone_services failed: no _runestone-services.xml file found in _static directory" + raise RuntimeError(msg) + def _place_runestone_services(tmp_dir, stringparams, ext_rs_methods): '''Obtain Runestone Services and place in _static directory of build''' From de61abf6f9bf0cf06d5797564f99574911701c98 Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Tue, 6 May 2025 15:14:03 -0700 Subject: [PATCH 09/16] Script: add profiling checkpoints to html() --- pretext/lib/pretext.py | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/pretext/lib/pretext.py b/pretext/lib/pretext.py index 75552bb0b6..a89b3c14cc 100644 --- a/pretext/lib/pretext.py +++ b/pretext/lib/pretext.py @@ -91,6 +91,8 @@ # contextmanager tools import contextlib +import time + # cleanup multiline strings used as source code import textwrap @@ -4879,6 +4881,9 @@ def html(xml, pub_file, stringparams, xmlid_root, file_format, extra_xsl, out_fi # to ensure provided stringparams aren't mutated unintentionally stringparams = stringparams.copy() + log_time_info = stringparams.get("profile-py", False) == "yes" + time_logger = Stopwatch("html()", log_time_info) + # Consult publisher file for locations of images generated_abs, external_abs = get_managed_directories(xml, pub_file) # Consult source for additional files @@ -4889,6 +4894,7 @@ def html(xml, pub_file, stringparams, xmlid_root, file_format, extra_xsl, out_fi pub_vars = get_publisher_variable_report(xml, pub_file, stringparams) include_static_files = get_publisher_variable(pub_vars, 'portable-html') != "yes" + time_logger.log("pubvars loaded") if include_static_files: # interrogate Runestone server (or debugging switches) and populate @@ -4898,6 +4904,7 @@ def html(xml, pub_file, stringparams, xmlid_root, file_format, extra_xsl, out_fi # even if we don't need static files, we need to set stringparams for # Runestone Services information. _cdn_runestone_services(stringparams, ext_rs_methods) + time_logger.log("runestone placed") # support publisher file, and subtree argument if pub_file: @@ -4916,18 +4923,19 @@ def html(xml, pub_file, stringparams, xmlid_root, file_format, extra_xsl, out_fi # place managed directories - some of these (Asymptote HTML) are # consulted during the XSL run and so need to be placed beforehand copy_managed_directories(tmp_dir, external_abs=external_abs, generated_abs=generated_abs, data_abs=data_dir) + time_logger.log("managed directories copied") if include_static_files: # Copy js and css, but only if not building portable html # place JS in scratch directory copy_html_js(tmp_dir) - - # build or copy theme build_or_copy_theme(xml, pub_vars, tmp_dir) + time_logger.log("css/js copied") # Write output into temporary directory log.info("converting {} to HTML in {}".format(xml, tmp_dir)) xsltproc(extraction_xslt, xml, None, tmp_dir, stringparams) + time_logger.log("xsltproc complete") if not(include_static_files): # remove latex-image generated directories for portable builds @@ -4963,6 +4971,8 @@ def html(xml, pub_file, stringparams, xmlid_root, file_format, extra_xsl, out_fi else: raise ValueError("PTX:BUG: HTML file format not recognized") + time_logger.log("build completed") + def revealjs( xml, pub_file, stringparams, xmlid_root, file_format, extra_xsl, out_file, dest_dir @@ -6282,6 +6292,29 @@ def place_latex_package_files(dest_dir, journal_name, cache_dir): shutil.copy2(file_path, dest_dir) +class Stopwatch: + """A simple stopwatch class for measuring elapsed time. """ + """print_log set to false disables logging of elapsed time """ + + def __init__(self, name:str="", print_log:bool=True): + self.name = name + self.print_log = print_log + self.start_time = time.time() + self.last_log_time = self.start_time + + def reset(self): + """Reset the log timer to the current time.""" + self.last_log_time = time.time() + + def log(self, timepoint_description:str=""): + """Print a log message with the elapsed time since the last log event.""" + if self.print_log: + cur_time = time.time() + elapsed_time = cur_time - self.start_time + since_last_log_time = cur_time - self.last_log_time + self.reset() + log.info(f"** Timing report from {self.name}: {timepoint_description}, {since_last_log_time:.2f}s since last watch reset. {elapsed_time:.2f}s total elapsed time.") + ########################### # From b88d7e46ea520b041c9d67863deb56abc63c5d92 Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Tue, 6 May 2025 13:41:17 -0700 Subject: [PATCH 10/16] HTML: add html.build-incremental stringparam --- xsl/pretext-html.xsl | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/xsl/pretext-html.xsl b/xsl/pretext-html.xsl index 1de463b121..0dddc7bd64 100644 --- a/xsl/pretext-html.xsl +++ b/xsl/pretext-html.xsl @@ -102,7 +102,15 @@ along with MathBook XML. If not, see . - + + + + + + + + + From a3c21bab8cf862aba0dc205eee59122ff413c54a Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Tue, 6 May 2025 17:17:48 -0700 Subject: [PATCH 11/16] Script: add html-incremental target --- pretext/lib/pretext.py | 35 +++++++++++++++++++++++++++++++++++ pretext/pretext | 31 +++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/pretext/lib/pretext.py b/pretext/lib/pretext.py index a89b3c14cc..09aab0c9db 100644 --- a/pretext/lib/pretext.py +++ b/pretext/lib/pretext.py @@ -4974,6 +4974,41 @@ def html(xml, pub_file, stringparams, xmlid_root, file_format, extra_xsl, out_fi time_logger.log("build completed") +def html_incremental(xml, pub_file, stringparams, xmlid_root, extra_xsl, dest_dir): + """Update an HTML incrementally in place. + Depends on _static and generated files already being in the destination directory. + Caller must supply: + * stringparams supplemented with: + * rs-js, rs-css, and rs-version (can use _set_runestone_stringparams to set) + * publisher: path to publisher file for use by xsltproc + """ + if not "rs-js" in stringparams: + log.error("Incremental build missing needed stringparam(s). Unable to complete build.") + return False + + # to ensure provided stringparams aren't mutated unintentionally + stringparams = stringparams.copy() + + log_time_info = stringparams.get("profile-py", False) == "yes" + time_logger = Stopwatch("html_incremental()", log_time_info) + + # support publisher file, and subtree argument + if pub_file: + stringparams["publisher"] = pub_file + if xmlid_root: + stringparams["subtree"] = xmlid_root + + # Optional extra XSL could be None, or sanitized full filename + if extra_xsl: + extraction_xslt = extra_xsl + else: + extraction_xslt = os.path.join(get_ptx_xsl_path(), "pretext-html.xsl") + + log.info("incremental convertsion of {} to HTML in {}".format(xml, dest_dir)) + xsltproc(extraction_xslt, xml, None, dest_dir, stringparams) + time_logger.log("xsltproc complete") + + def revealjs( xml, pub_file, stringparams, xmlid_root, file_format, extra_xsl, out_file, dest_dir ): diff --git a/pretext/pretext b/pretext/pretext index 2975c59ec7..820cdada79 100755 --- a/pretext/pretext +++ b/pretext/pretext @@ -783,6 +783,37 @@ def main(): dest_dir, None ) + elif args.format == "html-incremental": + # ----------------------------------------- + # Setup - this work could be done one time in a frontend that is monitoring changes + # Force incremental build flag + stringparams["html.build-incremental"] = "yes" + + log_time_info = stringparams.get("profile-py", False) == "yes" + time_logger = ptx.Stopwatch("pretext:html-incremental", log_time_info) + + # attempt to reuse RS services + if "debug.rs.dev" in stringparams: + rs_js, rs_css, rs_cdn_url, rs_version, services_xml = ptx._runestone_debug_service_info() + else: + rs_js, rs_css, rs_cdn_url, rs_version = ptx.query_existing_runestone_services( + dest_dir=dest_dir, + stringparams=stringparams + ) + ptx._set_runestone_stringparams(stringparams, rs_js, rs_css, rs_version) + time_logger.log("runestone stringparams set") + + # ----------------------------------------- + # Actual incremental build, this is the only work done on each change + ptx.html_incremental( + xml=xml_source, + pub_file=publication_file, + stringparams=stringparams, + xmlid_root=args.xmlid, + extra_xsl=extra_stylesheet, + dest_dir=dest_dir, + ) + time_logger.log("complete incremental build") elif args.format == "html-zip": # no "subtree root" build is possible ptx.html( From a236cb33e8b0f7edeef026e8190ab81c5b76a0da Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Tue, 6 May 2025 13:42:04 -0700 Subject: [PATCH 12/16] HTML: do not build search in incremental build --- xsl/pretext-html.xsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xsl/pretext-html.xsl b/xsl/pretext-html.xsl index 0dddc7bd64..eaec477963 100644 --- a/xsl/pretext-html.xsl +++ b/xsl/pretext-html.xsl @@ -310,7 +310,7 @@ along with MathBook XML. If not, see . - + From d9d14441c39d32b78670d9395518d73d362ba476 Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Wed, 7 May 2025 11:23:37 -0700 Subject: [PATCH 13/16] HTML: interactive build only provides warnings for current subtree --- xsl/pretext-html.xsl | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/xsl/pretext-html.xsl b/xsl/pretext-html.xsl index eaec477963..abd7e085dd 100644 --- a/xsl/pretext-html.xsl +++ b/xsl/pretext-html.xsl @@ -302,9 +302,21 @@ along with MathBook XML. If not, see . - - - + + + + + + + + + + + + + + + From 169e4be058850d2dca5c8bc5abf1bc0ec7452194 Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Wed, 7 May 2025 07:49:12 -0700 Subject: [PATCH 14/16] HTML: add html.build-preview stringparam --- xsl/pretext-html.xsl | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/xsl/pretext-html.xsl b/xsl/pretext-html.xsl index abd7e085dd..574ff7415e 100644 --- a/xsl/pretext-html.xsl +++ b/xsl/pretext-html.xsl @@ -104,13 +104,20 @@ along with MathBook XML. If not, see . - + - - - + + + + + + + + + + - + From fc68534a3a8388af9c8da7ec39828529fda234b0 Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Tue, 6 May 2025 15:42:40 -0700 Subject: [PATCH 15/16] Assembly: add prunning tree between labeled and webwork --- xsl/pretext-assembly.xsl | 94 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 2 deletions(-) diff --git a/xsl/pretext-assembly.xsl b/xsl/pretext-assembly.xsl index 70bb6178f2..27ac84b14c 100644 --- a/xsl/pretext-assembly.xsl +++ b/xsl/pretext-assembly.xsl @@ -355,6 +355,65 @@ along with PreTeXt. If not, see . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -476,12 +535,43 @@ along with PreTeXt. If not, see . + + + + + + + + + + + + + + + + + + + + + + + + + + + + PTX:INFO: Pruned build tree to out of original nodes. + + + - + - + From 030e67f13971dcf1fa243942be65eacc32f3114f Mon Sep 17 00:00:00 2001 From: Andrew Scholer Date: Tue, 6 May 2025 15:53:33 -0700 Subject: [PATCH 16/16] HTML: add warning to page when built with build-preview --- css/components/elements/_misc-content.scss | 10 ++++++++++ xsl/pretext-html.xsl | 3 +++ 2 files changed, 13 insertions(+) diff --git a/css/components/elements/_misc-content.scss b/css/components/elements/_misc-content.scss index 7a43c8bcbb..83265a4cfc 100644 --- a/css/components/elements/_misc-content.scss +++ b/css/components/elements/_misc-content.scss @@ -151,6 +151,16 @@ article.theorem-like .emphasis { font-style: oblique; } +.preview-build-warning { + background-color: rgb(249, 240, 240); + border: 2px solid rgb(202, 38, 38); + border-radius: 2px; + color: #333; + padding: 10px; + margin: 10px 0; +} + + /* Adapted from William Hammond (attributed to David Carlisle) */ /* "mathjax-users" Google Group, 2015-12-27 */ diff --git a/xsl/pretext-html.xsl b/xsl/pretext-html.xsl index 574ff7415e..5c68828068 100644 --- a/xsl/pretext-html.xsl +++ b/xsl/pretext-html.xsl @@ -11389,6 +11389,9 @@ along with MathBook XML. If not, see .
+ +
Preview build. Links and knowls that cross pages may not function correctly.
+