Skip to content
Merged
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
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ Instructions: Add a subsection under `[Unreleased]` for additions, fixes, change

## [Unreleased]

### Fixed

- Bug in which qrcodes don't generate for video/audio if no interactive or youtube elements exist.

### Changed

- qrcodes for pdf are now generated based on a hash of the elements they point to in addition to the baseurl for the publication file.

## [2.25.0] - 2025-07-26

Includes updates to core through commit: [45be2cf](https://github.com/PreTeXtBook/pretext/commit/45be2cfe85fd54a3e5c03743226919eb1a6b2085)
Expand Down
76 changes: 66 additions & 10 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pretext/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
VERSION = get_version("pretext", Path(__file__).parent.parent)


CORE_COMMIT = "45be2cfe85fd54a3e5c03743226919eb1a6b2085"
CORE_COMMIT = "f15f9b9fee75331d64d0fff4d757c479ef85fcb7"


def activate() -> None:
Expand Down
18 changes: 9 additions & 9 deletions pretext/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"codelens",
"datafile",
"interactive",
"qrcode",
"mermaid",
"myopenmath",
"dynamic-subs",
Expand All @@ -50,6 +51,7 @@
"codelens",
"datafile",
"interactive",
"qrcode",
"mermaid",
"myopenmath",
"dynamic-subs",
Expand All @@ -63,6 +65,7 @@
"codelens",
"datafile",
"interactive",
"qrcode",
"mermaid",
"myopenmath",
"dynamic-subs",
Expand All @@ -76,6 +79,7 @@
"codelens",
"datafile",
"interactive",
"qrcode",
"mermaid",
"myopenmath",
"dynamic-subs",
Expand Down Expand Up @@ -116,6 +120,7 @@
"codelens",
"datafile",
"interactive",
"qrcode",
"mermaid",
"myopenmath",
"dynamic-subs",
Expand All @@ -132,6 +137,7 @@
"codelens": ".//program[@interactive = 'codelens']",
"datafile": ".//datafile",
"interactive": ".//interactive",
"qrcode": ".//audio[@source|@href]|.//video[@source|@href|@youtube|@youtubeplaylist|@vimeo]|.//interactive",
"mermaid": ".//mermaid",
"myopenmath": ".//myopenmath",
"dynamic-subs": ".//statement[.//fillin and ancestor::exercise/evaluation]",
Expand All @@ -144,8 +150,9 @@
"sageplot": ["sageplot"],
"asymptote": ["asymptote"],
"prefigure": ["prefigure"],
"youtube": ["youtube", "play-button", "qrcode"],
"interactive": ["preview", "qrcode"],
"youtube": ["youtube", "play-button"],
"interactive": ["preview"],
"qrcode": ["qrcode"],
"codelens": ["trace"],
"datafile": ["datafile"],
"mermaid": ["mermaid"],
Expand All @@ -159,14 +166,12 @@
"latex-image": [],
"sageplot": ["pdf", "png"],
"prefigure": ["pdf"],
"mermaid": ["png"],
},
"latex": {
"asymptote": ["pdf"],
"latex-image": [],
"sageplot": ["pdf", "png"],
"prefigure": ["pdf"],
"mermaid": ["png"],
},
"html": {
"asymptote": ["html"],
Expand All @@ -185,20 +190,17 @@
"latex-image": ["svg"],
"sageplot": ["svg"],
"prefigure": ["svg"],
"mermaid": ["png"],
},
"kindle": {
"asymptote": ["png"],
"latex-image": ["png"],
"sageplot": ["png"],
"prefigure": ["png"],
"mermaid": ["png"],
},
"braille": {
"asymptote": ["all"],
"latex-image": ["all"],
"sageplot": ["all"],
"mermaid": ["png"],
},
"revealjs": {
"asymptote": ["html"],
Expand All @@ -210,14 +212,12 @@
"asymptote": [],
"latex-image": [],
"sageplot": [],
"mermaid": [],
},
"custom": {
"asymptote": ["all"],
"latex-image": ["all"],
"sageplot": ["all"],
"prefigure": ["all"],
"mermaid": ["png"],
},
}

Expand Down
44 changes: 30 additions & 14 deletions pretext/project/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,15 @@ class Format(str, Enum):


# The CLI only needs two values from the publication file. Therefore, this class ignores the vast majority of a publication file's contents, loading and validating only a (small) relevant subset.
# Since we will want to hash the baseurl for generating qr codes, we also load it here.
class PublicationSubset(
pxml.BaseXmlModel, tag="publication", search_mode=SearchMode.UNORDERED
):
external: Path = pxml.wrapped("source/directories", pxml.attr())
generated: Path = pxml.wrapped("source/directories", pxml.attr())
baseurl: t.Optional[str] = pxml.wrapped(
"html/baseurl", pxml.attr(name="href", default=None)
)


class BrailleMode(str, Enum):
Expand Down Expand Up @@ -517,6 +521,12 @@ def generate_asset_table(self) -> pt.AssetTable:
for node in source_assets:
assert isinstance(node, ET._Element)
hash.update(ET.tostring(node))
# For QR codes, we also hash the base URL, if it exists.
if asset == "qrcode":
base_url = self._read_publication_file_subset().baseurl
if base_url is not None:
hash.update(base_url.encode("utf-8"))
# Finally, we store the hash as a string in the dictionary.
asset_hash_dict[asset] = hash.hexdigest()
return asset_hash_dict

Expand Down Expand Up @@ -1123,6 +1133,26 @@ def generate_assets(
log.debug(e, exc_info=True)
# youtube also requires the play button.
self.ensure_play_button()
if "qrcode" in assets_to_generate:
try:
# Warn if trying to generate qrcodes without a base URL.
base_url = self._read_publication_file_subset().baseurl
if base_url is None:
log.warning(
"You are trying to generate qrcodes, but the publication file does not have a base URL. "
+ "This will result in qrcodes that do not point to anything meaningful."
)
core.qrcode(
xml_source=self.source_abspath(),
pub_file=self.publication_abspath().as_posix(),
stringparams=stringparams_copy,
xmlid_root=xmlid,
dest_dir=self.generated_dir_abspath() / "qrcode",
)
successful_assets.append("qrcode")
except Exception as e:
log.error(f"Unable to generate some qrcodes:\n {e}")
log.debug(e, exc_info=True)
if "mermaid" in assets_to_generate:
try:
core.mermaid_images(
Expand Down Expand Up @@ -1162,20 +1192,6 @@ def generate_assets(
except Exception as e:
log.error(f"Unable to generate some datafiles:\n {e}")
log.debug(e, exc_info=True)
# Finally, also generate the qrcodes for interactive and youtube assets:
# NOTE: we do not currently check for success of this for saving assets to the asset cache.
if "interactive" in assets_to_generate or "youtube" in assets_to_generate:
try:
core.qrcode(
xml_source=self.source_abspath(),
pub_file=self.publication_abspath().as_posix(),
stringparams=stringparams_copy,
xmlid_root=xmlid,
dest_dir=self.generated_dir_abspath() / "qrcode",
)
except Exception as e:
log.error(f"Unable to generate some qrcodes:\n {e}", exc_info=True)
log.debug(e, exc_info=True)
# Delete temporary directories left behind by core:
try:
core.release_temporary_directories()
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ plastex = "^3"
jinja2 = "^3"
coloraide = "^4"
pelican = { extras = ["markdown"], version = "^4.10", optional = true }
prefig = { extras = ["text"], version = "^0.3.6", optional = true }
prefig = { extras = ["text"], version = "^0.3.9", optional = true }


# Development dependencies
Expand Down