-
Notifications
You must be signed in to change notification settings - Fork 79
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
Add urlAttribute
helper that uses baseURI
(used for href
, src
etc.)
#154
base: main
Are you sure you want to change the base?
Conversation
…mageElement.src, etc.
@@ -14,8 +14,8 @@ class HTMLAnchorElement extends HTMLElement { | |||
} | |||
|
|||
/* c8 ignore start */ // copy paste from img.src, already covered | |||
get href() { return encodeURI(stringAttribute.get(this, 'href')); } |
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.
The getter/setter for href
used to encode/decode the URI, and this change breaks some tests. Should this technique be adopted inside urlAttribute
?
Browser behavior is below:
let a = document.createElement('a');
a.href = 'https://google.com/?q=asd&lol=<2>';
a.href
// "https://google.com/?q=asd&lol=%3C2%3E"
a.getAttribute('href')
// "https://google.com/?q=asd&lol=<2>"
Should we also store the raw value in the attribute, and encode it on the getter?
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 tests break it means we'll break working code out there ... this change shouldn't require a major though, should it?
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.
P.S. yes, we might want to encodeURI
on the URL returned href, if URL returned href is not encoded already
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.
... which it does ...
new URL('/?q=asd&lol=<2>', 'https://google.com/').href
// "https://google.com/?q=asd&lol=%3C2%3E"
so we want this behavior, I would drop the encoding but I am not sure we should drop the decoding ... the encoding is provided by the URL on current attribute which is the raw value, the decoding in assignment looks like still necessary to preserve the raw value ... this should not break anything, just remove the encodeURI in the getter.
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 need to read a bit more to understand how to align with the HTML spec (if possible). The immediate fix for the breaking test is:
return new URL(attr, element.baseURI ?? undefined).href;
(baseURI
is null
in the absence of an explicit location
or <base>
element, and that's an invalid base URL.)
But the problem is the getter returns either the encoded or unencoded value depending on the validity of baseURI
, and I wonder if that's the case in browsers as well.
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.
The current implementation of baseURI
is aware of <base>
right now, but if speed is a concern this needs to be cached or otherwise optimized, so that might complicate things:
get baseURI() {
const ownerDocument = this.nodeType === DOCUMENT_NODE ?
this : this.ownerDocument;
if (ownerDocument) {
const base = ownerDocument.querySelector('base');
if (base)
return base.getAttribute('href');
const {location} = ownerDocument.defaultView;
if (location)
return location.href;
}
return null;
}
Let me know if you think this feature is worth it in relation with your goals / use-cases for linkedom
. This has been an interesting rabbit hole regardless!
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.
uhm ... I see ... then return null
should be return 'about:blank'
... right? I don't think this would break much code out there but it is, technically, a breaking change, due returning non falsy value when no case is met ... bummer!
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, I don't see a big problem with return 'about:blank';
although it's technically a breaking change, as is I guess changing the behavior of URL-like element attributes. What I'm more concerned is how to get rid of the inefficient querySelector
each time you request href
on a link, and still update the value when you mutate the DOM.
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.
The cached version of this module doesn't care about repeated qS/qSA operation if the DOM didn't mutate in the meanwhile, so if that's a concern, just use the cached version instead?
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.
That is linkedom/cached
import, instead of the regular one https://github.com/WebReflection/linkedom#are-childnodes-and-children-always-computed
@@ -66,7 +66,7 @@ export class Node extends EventTarget { | |||
const ownerDocument = this.nodeType === DOCUMENT_NODE ? | |||
this : this.ownerDocument; | |||
if (ownerDocument) { | |||
const base = ownerDocument.querySelector('base'); |
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.
<base>
elements without a href
attribute should be skipped here. The algorithm is a bit more complicated (allowing for relative href
), but maybe that can be addressed more thoroughly in a future PR.
Fixes #153 by adding an
urlAttribute
helper to use in IDL properties that need to reflect HTML attributes representing an URL, such asHTMLAnchorElement.href
,HTMLImageElement.src
, etc.