Skip to content

sitemap a11y improvements#5312

Open
StephDriver wants to merge 45 commits into
r-v1.9.xfrom
b-5170_a11y_sitemaps
Open

sitemap a11y improvements#5312
StephDriver wants to merge 45 commits into
r-v1.9.xfrom
b-5170_a11y_sitemaps

Conversation

@StephDriver

Copy link
Copy Markdown
Member

closes #5170

@StephDriver

This comment was marked as outdated.

@StephDriver
StephDriver force-pushed the b-5170_a11y_sitemaps branch from 77a482e to ea56f0e Compare May 19, 2026 15:50
@StephDriver

This comment was marked as outdated.

@StephDriver

This comment was marked as resolved.

@StephDriver
StephDriver force-pushed the b-5170_a11y_sitemaps branch from 447b61b to d853bbc Compare June 1, 2026 15:01
@StephDriver
StephDriver marked this pull request as ready for review June 1, 2026 15:05
@StephDriver
StephDriver requested a review from mauromsl June 1, 2026 15:05
@StephDriver

Copy link
Copy Markdown
Member Author

Work Done:

  • updated the CMS pages to have drafts (with previews) and tidied up the CMS interface a bit. Then we can use CMS published pages as source of truth for additional pages for sitemaps.
  • changed utils/tests.py into a package and separated out the sitemap tests.
  • rewrote generate_sitemaps from ground up, to use a different structure that would validate with sitemaps schema, and satisfy WCAG requirements for link deduplication and disambiguation.
  • updated the progress bars while running the generator to show number of sitemaps per object.
  • created a new template_tag for linking to sitemap from each front of house footer.
  • wrote a new set of tests for this new generate_sitemaps.
  • split the original sitemaps-and-robots.md and then updated the sitemaps part, with tables to explain which pages are included in sitemaps and when (lots and lots of logic to cover). I have reconciled these back to the tests.
  • manual tests of new sitemaps alongside automated tests
    • loading them up and moving around the structure.
    • git tracked the sitemaps output, so that I could confirm they were consistently generated.
    • checked back and forth from the new sitemap footer links.

Notes:

  1. a11y-mode work will also need to be updated to include this footer link too. see Add sitemap footer link to Accessibility mode templates clarity#7
  2. Original docs recommended setting chron to run generate_sitemap every 30 min. Is this still wise? This is a lot of processing. Do we need to consider some kind of incremental update command.
  3. There's a lot of logic. I have been over it line by line several times until my eyes blurred - good luck with it.
  4. This moved beyond what was described in the original issues because we needed a source of truth for which CMS pages to include, and having explored using the Nav, it was clear the better solution was to introduce draft/publish flags for CMS. Further, the structure had to be amended to pass the validation, as we could only have either URLs or site-indexes listed on any one sitemap, we couldn't mix them.

@mauromsl
mauromsl changed the base branch from master to r-v1.9.x June 4, 2026 07:55
@ajrbyers ajrbyers assigned StephDriver and unassigned mauromsl Jun 4, 2026
@ajrbyers
ajrbyers self-requested a review June 4, 2026 09:21
@StephDriver
StephDriver force-pushed the b-5170_a11y_sitemaps branch from d853bbc to 043cba5 Compare June 4, 2026 10:18
@StephDriver StephDriver assigned ajrbyers and unassigned StephDriver Jun 4, 2026
@StephDriver

Copy link
Copy Markdown
Member Author

rebased onto r-v1.9.x

@StephDriver
StephDriver force-pushed the b-5170_a11y_sitemaps branch from 043cba5 to b087979 Compare June 18, 2026 10:11
@ajrbyers ajrbyers assigned StephDriver and unassigned ajrbyers Jun 19, 2026
@ajrbyers

Copy link
Copy Markdown
Member

@StephDriver passed this back as tests are failing here.

@StephDriver

This comment was marked as outdated.

@ajrbyers

This comment was marked as outdated.

@StephDriver

Copy link
Copy Markdown
Member Author

@ajrbyers which tests? All of mine are passing.

...

Well never make an assumption. Its actually ruff formatting see: https://github.com/openlibhums/janeway/actions/runs/27752395486/job/82105825907?pr=5312

ooh, that's interesting, because I was running a formatter with a pre-commit hook - which won't let me commit until it passes, so that means my formatter is out of sync with the one testing here. I'll have to dig into it more on Monday as to what and why.

@StephDriver

Copy link
Copy Markdown
Member Author

I haven't worked out why my existing hook wasn't firing for that file, when it fired for others - the most likely explanation is that it the difference crept in during a rebase. But the two missing empty lines have now been duly added.

@StephDriver StephDriver assigned ajrbyers and unassigned StephDriver Jun 22, 2026
@mauromsl mauromsl assigned mauromsl and unassigned ajrbyers Jun 25, 2026
@StephDriver

StephDriver commented Jun 26, 2026

Copy link
Copy Markdown
Member Author

Unpicking the test failures.

  • sorted out the migrations
  • updated the ruff formatting and added new guard as it was testing disc versions not staged versions pre commit. ruff pre-commit git-hook targets disk not staged files #5360
  • went through all my new tests, updated them - found an error in my code relating to how draft access codes where handled (it allowed reuse) - fixed that, and updated tests around this new behaviour.
  • tested locally with python 3.11 (as that is the one that keeps failing here) - I usually work in python 3.12, and I couldn't reproduce the errors here with that. Can't actually reproduce the problem with either.

Failures that are on the base branch too

  • ERROR: test_pdf_to_text (src.core.tests.test_files.TestFilesHandler.test_pdf_to_text)
  • FAIL: test_search_includes_article (src.journal.tests.test_journal_frontend.TestJournalSite.test_search_includes_article)
  • FAIL: test_section_editor_cannot_see_pii_when_enabled

I cannot reproduce the test errors from github locally. They seem to come down to submission_article.primary_issue_id which I refer to here, but I didn't create. So my best guess is some kind of missing migration - but that's only affecting GH and not local?

@StephDriver
StephDriver force-pushed the b-5170_a11y_sitemaps branch from 8522ecf to 2033ddc Compare June 26, 2026 14:41

@mauromsl mauromsl left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly comments regarding cleanup of migrations, unused code and inline import statements.

The more important comment is around the change to the lastmod attribute on article sitemaps. Do you agree that giving a false and potentially outdated lastmod date could be problematic?

Finally a note around performance: I've noted we run a large number of loops during title / date processing of issue items and preprints, including N+1 queries. For publications that run larger items (big repositories or conference proceedings) Would it be worth breaking these sitemaps into smaller ones? My concerns:

  • Memory consumption: Since we have to hold all the model instances in memory in order to disambiguate dates/titles, memory requirements for some instances might be very high. Optmise by memoizing only the title and date strings we are worried about
  • Compute time: Each of the disambiguation / processing done per sitemap, comes with its own loop. Instead build the dictionary of memoized strings on the caller and pass it to the children to only run a single loop and do checks in constant time.
  • (Probably not an issue but worth mentioning) There is a 10MB file size limit and 50K link limit per sitemap on sitemaps.org recommendations.

I can help providing prod-like data to test these if you need them @StephDriver

Comment thread src/cms/models.py
Comment on lines +77 to +83
if self.is_draft and not self.preview_token:
self.preview_token = uuid4()
elif self.pk:
existing = Page.objects.get(pk=self.pk)
if self.is_draft and not existing.is_draft:
self.preview_token = uuid4()
super().save(*args, **kwargs)

@mauromsl mauromsl Jul 15, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of doing these checks (which won't run when an object is created without calling .save()explicitely), is there a reason to not use an uuid fieldwith a default like the one provided in the docs as an example:

preview_token = models.UUIDField(default=uuid.uuid4, editable=False)

If the reason is that we want to cycle them, I question why we need to do that instead of having a token for the lifetime of the page

@StephDriver StephDriver Jul 16, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mauromsl

My take on this was that each time the page becomes a draft it needs a different token because the token grants anonymous access to that draft. A page could exist for years. Staff could change. Allowing old links (i.e old staff) to access that page during new drafts felt like it could be a problem and not what a user would expect. I realise 99.9999% of the time it likely wouldn't matter. But it seemed good practice to me to keep it unique per drafting process for a page, rather than unique per page.

Comment thread src/cms/views.py Outdated
Comment on lines +76 to +77
if not page.is_draft:
page.preview_token = str(uuid4())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we provide a token to all pages, we do not need to do this check whenever a page is toggled. Also, toggling the page as draft multiple times would reset the token, which I'm not sure we want. Finally, the same token generation logic lives inside the .save() call below.

Comment thread src/cms/views.py Outdated
Comment thread src/cms/views.py Outdated
Comment thread src/core/templatetags/sitemap_tags.py Outdated
Comment thread src/utils/logic.py
)
repos = repo_models.Repository.objects.filter(live=True)
clash_names = _build_clash_names(press)
press_label = _suffixed_name(press.name, clash_names, "[press]")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where is press_label used?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread src/utils/logic.py
is_remote=False,
)
repos = repo_models.Repository.objects.filter(live=True)
clash_names = _build_clash_names(press)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is clash_names used

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread src/utils/logic.py
Comment on lines +930 to +933
clash_names = _local_clash_names(repo.name, press.name)
repo_label = _suffixed_name(repo.name, clash_names, "[repository]")
press_label = _suffixed_name(press.name, clash_names, "[press]")
child_sitemaps = [

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we are using these here either

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread src/core/include_urls.py Outdated
Comment thread src/core/templatetags/sitemap_tags.py Outdated
@mauromsl mauromsl assigned StephDriver and unassigned mauromsl Jul 16, 2026
@mauromsl mauromsl added this to the 1.9 Final Push milestone Jul 16, 2026
@StephDriver
StephDriver force-pushed the b-5170_a11y_sitemaps branch from 5999aae to 91e014c Compare July 17, 2026 09:49
@StephDriver StephDriver assigned mauromsl and unassigned StephDriver Jul 17, 2026
@StephDriver

Copy link
Copy Markdown
Member Author

@mauromsl when testing these changes I found that the repo A11y page was falling back to the press page, but that's because we don't have repo data yet, and haven't built a repo version. So it shouldn't be there at all and the sitemaps shouldn't be listing it. So I've added another commit to remove that link from Repo footers and sitemaps.

I also found the material repository had no footer link to the sitemap, so I added that too.

@StephDriver
StephDriver requested a review from mauromsl July 17, 2026 12:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve Front of House Sitemaps

3 participants