-
-
Notifications
You must be signed in to change notification settings - Fork 8.6k
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
feat: add eslint plugin no-html-links #8156
Conversation
✅ [V2]
To edit notification comments on pull requests, go to your Netlify site settings. |
⚡️ Lighthouse report for the deploy preview of this PR
|
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.
Thanks, LGTM 👍
Wonder if we want to be that strict and never allow any absolute URL by default, so maybe adding an option can be convenient?
We mostly want to prevent bad relative links IMHO
Any opinion @Josh-Cena ?
</blockquote> | ||
<figcaption> | ||
<a href={profileUrl} target="_blank" rel="noreferrer nofollow"> |
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.
<Link>
doesn't automatically apply nofollow.
Maybe use <Link rel="nofollow">
. Open question: should the rel be merged into existing ones ("noreferrer noopener") or override?
I assume merging is fine because we generally don't want to remove "noopener noreferrer" from external links (and could use <a>
as an escape hatch)
<a | ||
href={`#${heading.id}`} | ||
<Link | ||
to={`#${heading.id}`} |
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.
wonder if we could also allow <a>
for hardcoded hash links?
(not all links can be evaluated but hardcoded ones could? Maybe eslint can know it starts with a hash? 🤷♂️)
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.
It's not undoable. Even for template literals, you just need to check quasis[0][0] === "#"
.
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.
Good point!
Lets say that we add this to the plugin, should it still warn (encourage) the user to use <Link>
instead of the a tag?
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 guess we can just ignore hashes. This is a bonus, we can merge this PR without this feature if complicated to implement.
An option like |
Not sure "fully resolved" is very common, where does it come from?
Agree, but maybe we'll need to improve it for external links then , because for example not merging |
Thanks for the thorough feedback, will add some changes tomorrow 🙇 . |
I'd say, anything that starts with a protocol should be ignored. |
agree At the same time is It looks like the concept of "fully qualified" exist for domain names (https://www.rfc-editor.org/rfc/rfc6454 https://en.wikipedia.org/wiki/Fully_qualified_domain_name) but can't really find any official ref of "fully qualified URL" in any spec). I don't know where "fully resolved" comes from but it doesn't seem like an existing concept either. I'm more used to see the term "fully qualified" and some sources seem agree despite being web authorities (https://gateway.force.com/DPGCustHelp/s/article/Fully-qualified-URL) |
I was thinking about "fully resolved paths". I don't know where that term crosses my mind either. |
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.
LGTM, good enough to merge
Just wondering if "ignoreFullyResolved" is the best term we can use to represent the option, any opinion before merging?
|
||
| Option | Type | Default | Description | | ||
| --- | --- | --- | --- | | ||
| `ignoreFullyResolved` | `boolean` | `false` | Set to true will not report any `<a>` tags with absolute URLs. | |
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 "fully resolved" === "absolute url" then maybe we'd want to be consistent?
https://www.rfc-editor.org/rfc/rfc3986#section-4.3
Maybe we just want "ignoreAbsoluteUrls" instead, it would be easier for users to understand?
This is just wording, but it remains important.
Now we can still do a breaking change later if we change our mind, not a huge deal.
I want to review this before merging. I think I can find some time this weekend |
# Conflicts: # packages/docusaurus-theme-classic/src/theme/SkipToContent/index.tsx
conflict resolved @Josh-Cena do you still want to review 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.
Extremely sorry for missing this @JohnVicke. The implementation looks good although I'd like to work on enhancements after this is merged. Just requesting a bit more tests (as ESLint plugin maintainers always do...) I could also do this myself this week so it gets merged ASAP
(attr): attr is TSESTree.JSXAttribute => attr.type === 'JSXAttribute' && attr.name.name === 'href', | ||
); | ||
|
||
if (hrefAttr?.value?.type === 'Literal') { |
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.
Could you add tests for when this is not a literal? Especially template literals. In the future I definitely want this rule to recognize some common interpolation patterns (e.g. if the template starts with /
then it's definitely not fullyResolved
), so it's better if we can have some tests to verify how the behaviors change.
@Josh-Cena let me know if you want to do something about this PR 🤪 otherwise I'll apply some suggestions, do a few minor changes and merge it |
Mostly LGTM. I wonder if we should add an option to ignore fully dynamic and not statically analyzable |
Co-authored-by: Joshua Chen <[email protected]>
Look good enough to merge Added some extra code to handle hardcoded/static template literal strings too For more dynamic cases where static analysis is possible, that can be handled in a follow-up PR Was wondering if it's possible to pre-evaluate AST nodes with TSESTree @Josh-Cena @JoshuaKGoldberg Apparently, Babel is able to do that successfully: Feel free to complete the missing cases if you know how to ;) |
Pre-flight checklist
Motivation
Described in: #6472
Test Plan
Jest unit tests are included.
Output of `yarn test no-html-plugins`
Test links
Docs preview: https://deploy-preview-8156--docusaurus-2.netlify.app/docs/api/misc/@docusaurus/eslint-plugin/no-html-links
Comments
The solution is fairly simple, I played around with when the message should be returned to the user (e.g. a tag has no attributes). However, if we want to enforce docusaurus links all the time this feels more accurate.