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
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [UNRELEASED]


* Fixed an issue with `HTMLTextDocument()` returning extracted `HTMLDependency()`s in a non-determistic order. (#95)

## [0.5.3] 2024-07-18

Expand Down
13 changes: 9 additions & 4 deletions htmltools/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1215,19 +1215,24 @@ def _static_extract_serialized_html_deps(
# HTMLdependency.get_tag_representation()
pattern = r'<script type="application/json" data-html-dependency="">((?:.|\r|\n)*?)</script>'
dep_strs = re.findall(pattern, html)
# Deduplicate dependencies. htmltools normally would dedupe dependencies, but
# with HTMLTextDocuments, the input HTML would usually have been generated by
# something else (like Quarto) and may not have the dependencies deduped.
dep_strs = list(set(dep_strs))

# Remove the serialized HTML dependencies from the HTML string
html = re.sub(pattern, "", html)

# Reconstitute the HTMLDependency objects
#
# Note: htmltools normally would dedupe dependencies, but
# with HTMLTextDocuments, the input HTML would usually have been generated by
# something else (like Quarto) and may not have the dependencies deduped.
seen_deps: set[str] = set()
deps: list[HTMLDependency] = []
for dep_str in dep_strs:
if dep_str in seen_deps:
continue
args = json.loads(dep_str)
dep = HTMLDependency(**args)
deps.append(dep)
seen_deps.add(dep_str)

return (html, deps)

Expand Down
6 changes: 3 additions & 3 deletions tests/test_html_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,9 +322,9 @@ def test_json_roundtrip():
x_str, deps_replace_pattern='<meta data-foo="">'
).render()

# Make sure both deps are present.
assert "testdep" in [d.name for d in rendered["dependencies"]]
assert "testdep2" in [d.name for d in rendered["dependencies"]]
# Make sure both deps are present and in the order they appear in x_str.
assert "testdep2" == rendered["dependencies"][0].name
assert "testdep" == rendered["dependencies"][1].name

# Make sure testdep was deduplicated by HTMLTextDocument().render().
assert rendered["dependencies"].count(testdep) == 1
Expand Down
Loading