Skip to content

fix(uve): open file-asset links in a new tab instead of loading them as pages (#35504) - #36925

Open
dsilvam wants to merge 1 commit into
mainfrom
issue-35504-pdf-link-new-tab
Open

fix(uve): open file-asset links in a new tab instead of loading them as pages (#35504)#36925
dsilvam wants to merge 1 commit into
mainfrom
issue-35504-pdf-link-new-tab

Conversation

@dsilvam

@dsilvam dsilvam commented Aug 6, 2026

Copy link
Copy Markdown
Member

Proposed Changes

  • Add isAssetPath() to the UVE utils — a predicate that distinguishes file-asset URLs from HTMLPage URLs. It matches dotCMS asset-delivery prefixes (/dA/, /dotAsset/, /contentAsset/) and otherwise mirrors the backend's own extension heuristic in Identifier#setURI: no extension (or the configured VELOCITY_PAGE_EXTENSION) means a page, any other real extension means a file.
  • Use it in handleInternalNav — a same-host href that resolves to a file asset now opens in a new tab and calls preventDefault(), instead of being handed to uveStore.pageLoad().
  • Tests for both.

Root cause

handleInternalNav split anchor clicks into exactly two buckets: different hostname → open a new tab; anything else → uveStore.pageLoad({ url: url.pathname, ... }). There was no check for whether the same-host target was actually an HTMLPage, so a link to a file asset (/dA/<inode>/fileAsset/doc.pdf, /application/files/doc.pdf) was fed to the Page API, which cannot resolve it. The editor then rendered its "Nothing Live Here Yet" / "Page not found" state.

Because the (internalNav) binding is unconditional, this affected Preview/Published mode as well as Edit mode — the linked issue is titled edit-mode-only, so please exercise both when testing.

Checklist

  • Tests
  • Translations — n/a, no user-facing strings added
  • Security Implications Contemplated

Security note: the new branch passes the already-resolved same-origin href to window.open. The external-host branch above it is unchanged and still handles cross-origin links, so this does not widen what can be opened; it only changes how same-origin file links are handled. No new user input is parsed — isAssetPath receives a URL.pathname that was already constructed upstream.

Test coverage

utils.spec.ts — 19 cases on isAssetPath:

  • Assets: /dA/.../report.pdf, /dA/ with no extension, /dotAsset/, /contentAsset/, /application/files/report.pdf, .docx, .mp4, .tar.gz, uppercase .PDF
  • Pages: /about-us/index, .html, .htm, .dot, /blog/, /
  • Regression guards: /blog/release-v1.2 and /news/2024.10 must stay pages — a naive extension check would read the trailing 2/10 as a file extension and break navigation to URL-map slugs
  • Edge: empty and nullish input

edit-ema-editor.component.spec.ts — 3 cases on handleInternalNav: a .pdf link and a /dA/ link each open a new tab, call preventDefault, and do not call pageLoad; an .html link still routes through pageLoad.

Full suite: 37/37 suites, 913 passed, 0 failures. nx lint portlets-edit-ema-portlet clean.

Additional Info

Verified manually against a locally built image: clicking /dA/<inode>/fileAsset/<name>.pdf in edit mode now opens the PDF in a new tab and leaves the editor on the page.

Note for reviewers/QA: the Angular bundle ships from the separate dotcms-core-web Maven module, so ./mvnw install -pl :dotcms-core -DskipTests without --am will silently test a stale frontend. Use ./mvnw install -pl :dotcms-core --am -DskipTests.

Two related items deliberately left out of scope:

  • The external-host branch (edit-ema-editor.component.ts, the url.hostname !== window.location.hostname case) opens a new tab but never calls preventDefault(), so an external link also navigates the iframe away. Same class of bug, one line, but unrelated to this issue.
  • An extensionless file asset served from a folder path outside /dA/ would still be treated as a page. Not reachable through the reported flow; a fully authoritative fix would need a backend round-trip per link click.

Refs: #35504, FD #36746

…as pages (#35504)

handleInternalNav treated every same-host link as an HTMLPage and fed it to the
Page API, so a link to a PDF resolved to a 404 "Page not found" in both edit and
preview mode. Add an isAssetPath() predicate that mirrors the backend extension
heuristic, and route hrefs resolving to a file asset to a new tab instead.

Refs: #35504, FD #36746

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant