Skip to content

Commit c26fc1a

Browse files
FITB: Dynamic substitutions require node modules be installed. (#1018)
* FITB: Dynamic substitutions require node modules be installed. * FITB: Match formatting with black * Some bookkeeping --------- Co-authored-by: Oscar Levin <oscar.levin@unco.edu>
1 parent 5221a27 commit c26fc1a

6 files changed

Lines changed: 71 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ Instructions: Add a subsection under `[Unreleased]` for additions, fixes, change
99

1010
## [Unreleased]
1111

12+
### Changed
13+
14+
- Generating dynamic substitutions now uses node instead of playwright. Node 22.10 or greater is required.
15+
1216
## [2.22.0] - 2025-07-05
1317

1418
Includes updates to core through commit: [e6f9288](https://github.com/PreTeXtBook/pretext/commit/e6f92889e1e4978f71d7417be410ca379d6e9eff)

pretext/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
VERSION = get_version("pretext", Path(__file__).parent.parent)
2020

2121

22-
CORE_COMMIT = "e6f92889e1e4978f71d7417be410ca379d6e9eff"
22+
CORE_COMMIT = "75e5bb36da237e2ddb11bec9454c8981c0d4897c"
2323

2424

2525
def activate() -> None:

pretext/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"codelens",
2727
"datafile",
2828
"myopenmath",
29+
"dynamic-subs",
2930
],
3031
"pdf": [
3132
"webwork",

pretext/project/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,7 @@ def generate_assets(
995995
# The dynamic-subs asset output is required for the subsequent asset generation, so needs to be near the top.
996996
if "dynamic-subs" in assets_to_generate:
997997
try:
998+
utils.ensure_dynsub_node_modules()
998999
core.dynamic_substitutions(
9991000
xml_source=self.source_abspath(),
10001001
pub_file=self.publication_abspath().as_posix(),

pretext/resources/__init__.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,22 @@ def install(reinstall: bool = False, npm_install: bool = False) -> None:
7474
log.warning(f"Unable to install npm packages for theme building: {e}")
7575
log.debug(e, exc_info=True)
7676
return
77+
# Dynamic substitution script requires node versions > 22.10
78+
os.chdir(_RESOURCE_BASE_PATH / "core" / "script" / "dynsub")
79+
try:
80+
npm_cmd = shutil.which("npm")
81+
if npm_cmd is None:
82+
log.warning(
83+
"Cannot find npm. Will not be able to extract dynamic substitutions."
84+
)
85+
raise FileNotFoundError
86+
subprocess.run([npm_cmd, "install"])
87+
except Exception as e:
88+
log.warning(
89+
f"Unable to install npm packages for dynamic substitutions: {e}"
90+
)
91+
log.debug(e, exc_info=True)
92+
return
7793

7894

7995
def resource_base_path() -> Path:

pretext/utils.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,54 @@ def ensure_css_node_modules() -> None:
559559
log.debug("", exc_info=True)
560560

561561

562+
def ensure_dynsub_node_modules() -> None:
563+
# Look for node_modules and install if we can.
564+
with working_directory(
565+
resources.resource_base_path() / "core" / "script" / "dynsub"
566+
):
567+
# Make sure node version is at least 22.10:
568+
try:
569+
node_cmd = shutil.which("node")
570+
if node_cmd is None:
571+
log.warning(
572+
"Node.js must be installed to extract dynamic substitutions. Please install node.js and npm."
573+
)
574+
raise FileNotFoundError
575+
node_version = subprocess.run([node_cmd, "-v"], capture_output=True)
576+
log.debug(f"Node version: {node_version.stdout.decode()}")
577+
node_version_decode = node_version.stdout.decode().split(".")
578+
main_version = int(node_version_decode[0][1:])
579+
sub_version = int(node_version_decode[1])
580+
if main_version < 22 | (main_version == 22 and sub_version < 10):
581+
log.warning(
582+
"Node version must be at least 22.10 to extract dynamic substitutions. Please update node.js and npm."
583+
)
584+
return
585+
except Exception as e:
586+
log.debug(e)
587+
log.debug("", exc_info=True)
588+
# Check if node_modules is already present:
589+
if Path("node_modules").exists():
590+
log.debug("Node modules already installed.")
591+
return
592+
# If not, try to install them:
593+
log.debug(
594+
"Attempting to install/update required node packages extract dynamic susbstitutions."
595+
)
596+
try:
597+
npm_cmd = shutil.which("npm")
598+
if npm_cmd is None:
599+
log.warning("Cannot find npm. Install npm and try again.")
600+
raise FileNotFoundError
601+
subprocess.run([npm_cmd, "install"])
602+
except Exception as e:
603+
log.warning(
604+
"Unable to install npm packages. Unable to extract dynamic substitutions."
605+
)
606+
log.warning(e)
607+
log.debug("", exc_info=True)
608+
609+
562610
def playwright_install() -> None:
563611
"""
564612
Run `playwright install` to ensure that its required browsers and tools are available to it.

0 commit comments

Comments
 (0)