Skip to content

Fix silent failures of Alt+O / Alt+C shortcuts - #2721

Merged
simon04 merged 6 commits into
freeCodeCamp:mainfrom
ryann-g:fix/alt-shortcuts-silent-failure
Sep 14, 2026
Merged

simon04 merged 6 commits into
freeCodeCamp:mainfrom
ryann-g:fix/alt-shortcuts-silent-failure

Conversation

@ryann-g

@ryann-g ryann-g commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Fixes #2634

What this PR does

Alt+O (open original page) and Alt+C (copy original link) currently fail completely silently when the rendered entry has no ._attribution ._attribution-link element, and Alt+C additionally had a leftover console.log and ignored clipboard promise rejections. This PR shows a transient notice when the link is unavailable, surfaces clipboard failures instead of swallowing them, and removes the debug logging.

Investigation notes

While debugging why the shortcuts "do nothing" for some users and work for others:

  • The cached entry data on documents.devdocs.io does contain the _attribution block (verified against e.g. git-status.html), so the selector input exists at the data level.
  • The failure mode is therefore environment- or page-dependent (stale service-worker caches serving pre-attribution HTML, docs whose scrapers render no attribution, or pages where attribution isn't the last child) — exactly the split reported in the issue (works on some macOS setups, dead on Windows/others).
  • Because both handlers bailed out with a bare return, every one of those cases produced identical "nothing happens" behavior, making the bug impossible to self-diagnose from the UI. Surfacing a notice turns the invisible state into actionable feedback.

Changes

  • entry_page.js: both handlers now show a transient notice ("The original page link is not available for this documentation") instead of silently returning; onAltC handles the navigator.clipboard.writeText rejection with its own notice; removed stray console.log
  • notice_tmpl.js: added noOriginalLinkNotice and copyFailedNotice templates following the existing pattern
  • New notices auto-dismiss after 3 seconds and replace each other rather than stacking

Testing

DevDocs has no JS unit-test infrastructure yet (#2673), so verification was: syntax check on both modified files plus manual code-path review against the cached-entry structure linked above. The notice path can be exercised by running any entry whose scraped HTML lacks an attribution block.

Happy to iterate if maintainers would prefer different wording/behavior (e.g. also attempting URL reconstruction for docs without attribution).

Alt+O (open original page) and Alt+C (copy original link) both bail out
silently when the rendered entry has no ._attribution ._attribution-link
element, which left users of affected documentations with dead shortcuts
and no feedback (freeCodeCamp#2634). Alt+C also logged to console on every use and
ignored clipboard promise rejections after the navigator.clipboard
migration.

- Show a transient notice when no original-page link exists
- Surface a notice if the clipboard write rejects instead of failing
  silently; drop the leftover console.log
- Notices auto-dismiss after 3s without stacking
@ryann-g
ryann-g requested a review from a team as a code owner August 23, 2026 16:20
@simon04
simon04 requested a balanced review from Copilot September 13, 2026 10:28

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Some identified page shapes and browser contexts still fail, and existing notices can obscure the new feedback.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Adds user-facing feedback when original-page shortcuts cannot locate or copy attribution links.

Changes:

  • Adds transient notices for unavailable links and clipboard failures.
  • Removes debug logging and handles clipboard promise rejections.
File summaries
File Description
assets/javascripts/views/content/entry_page.js Handles shortcut failures and transient notice lifecycle.
assets/javascripts/templates/notice_tmpl.js Defines the new notice messages.
Review details

Suppressed comments (2)

assets/javascripts/views/content/entry_page.js:235

  • The same :last-child constraint means this new fallback is shown even when a usable attribution link exists but attribution is not the final child. Alt+O therefore remains broken for a page shape explicitly called out in the investigation; use a selector that does not depend on sibling position.
      this.showTransientNotice("noOriginalLink");

assets/javascripts/views/content/entry_page.js:246

  • This transient notice can be invisible whenever a persistent Notice already exists, such as the single-doc notice (app/app.js:116) or disabled-doc notice (views/pages/hidden.js:10). Notice.show() prepends the new element, and all notices share the same absolute bounds and z-index, so the later persistent sibling paints over it. The transient notice needs an explicit stacking/lifecycle strategy that keeps it above an existing notice.
    this.transientNotice = new app.views.Notice(type);
  • Files reviewed: 2/2 changed files
  • Comments generated: 2
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread assets/javascripts/views/content/entry_page.js Outdated
Comment thread assets/javascripts/views/content/entry_page.js Outdated
The `._attribution:last-child` lookup failed whenever the attribution was
followed by another element, so Alt+O / Alt+C reported the link as
unavailable even though it existed. Match the last attribution link
instead, which keeps the previous intent (the appended attribution wins
over any inside the page content) without depending on sibling position.
`navigator.clipboard` is undefined in unsupported or non-secure browser
contexts, so Alt+C threw before the rejection handler could report the
failure. Check for the API up front and show the same notice.
All notices share the same absolute bounds and z-index, and `Notice.show()`
prepends, so the transient notice was painted over by an existing
single-doc or disabled-doc notice. Raise it with a `_notice-transient`
class, and route every teardown through `hideTransientNotice()` so the
notice can't outlive the page it was shown on.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

A delayed clipboard rejection can display a stale failure notice after navigation.

Get a fresh assessment by requesting another Copilot review.

Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment on lines +239 to +241
navigator.clipboard
.writeText(link.href + location.hash)
.catch(() => this.showTransientNotice("copyFailed"));

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Transient notices can incorrectly persist across entry-to-entry navigation.

Get a fresh assessment by requesting another Copilot review.

Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Balanced


deactivate() {
if (super.deactivate(...arguments)) {
this.hideTransientNotice();
@simon04
simon04 merged commit a374a88 into freeCodeCamp:main Sep 14, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Alt+O and Alt+C keyboard shortcuts are no longer working

3 participants