-
Notifications
You must be signed in to change notification settings - Fork 15
fix: Open external links in a new tab #120
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
cca8f4a
to
a227602
Compare
a227602
to
0b3e7b0
Compare
Have you tested that this works? I can confirm the |
Oh shoot, yeah I saw the |
Now a two step process: * Markdown renderer adds `data-external-link` to external links * DOMPurify adds `target="_blank" rel="noopener noreferrer"` to links with that attribute Otherwise sanitization strips out the target attribute.
@cpsievert okay, now it works! 😃 |
Makes it easier to stop propagation if you want to prevent the dialog from showing
window.open(linkEl.href, "_blank", "noopener,noreferrer") | ||
} | ||
}) | ||
.catch(() => { | ||
// If dialog fails for any reason, fall back to opening the link directly | ||
window.open(linkEl.href, "_blank", "noopener,noreferrer") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we're opening links this way, seems we could drop the afterSanitizeAttributes
hook?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or do we want to keep it for non-chat situations?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I remember deleting them, but maybe they crept back in?
}) | ||
} | ||
|
||
private createDialog(): void { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer this broken down into 2 methods: createDialog(): HTMLElement
and attachDialogListeners(x: HTMLElement): void
. Then do all state mutation at the top-level in connectedCallback()
// Check if the browser supports HTMLDialogElement | ||
if (typeof window.HTMLDialogElement !== "undefined") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I'm not sure if this is needed? It'd be a surprise to me if Bootstrap depended on <dialog>
, and also the browser support is pretty good https://caniuse.com/?search=HTMLDialog
} | ||
} | ||
|
||
export class ChatExternalLinkDialog extends LightElement { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be used in other non-chat scenarios, right? I don't want to make this a requirement, but perhaps worth noting that we could abstract this and re-use if/when we decide to do tool approval?
export class ChatExternalLinkDialog extends LightElement { | |
export class ExternalLinkDialog extends LightElement { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that's a good idea! But we own all the code here so we can just rename this when we get to that
@@ -380,6 +382,7 @@ class ChatContainer extends LightElement { | |||
) | |||
|
|||
this.inputSentinelObserver.observe(sentinel) | |||
this._boundOnExternalLinkClick = this.#onExternalLinkClick.bind(this) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit surprised the .bind()
is necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, we need it because we and the event listener to the window and not the chat container element
Fixes #11