-
Notifications
You must be signed in to change notification settings - Fork 159
Make event location links clickable #641
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?
Make event location links clickable #641
Conversation
|
looks good on first glance also in #621 we did specify that events should be clickable in the event description as well. you are welcome to add it to this PR, or if you'd like to split it out into a different PR that's fine too |
|
Accidentally closed the request lol. I'll try to get links in the description working on this PR too. |
|
It seems like it might be a good idea to use a library called react-linkify https://www.npmjs.com/package/react-linkify Is there anything special I need to consider when adding a new library? |
|
can you mention in the Discord to see if others have opinions? seems fine for me, but ideally we get 1-2 other sign offs before moving forward |
12d53a9 to
0efc32c
Compare
|
Links are now working int he event description as well! Thanks to @indifferentghost for the help! |
| if (URLRegex.test(res)) { | ||
| // Prepend http:// if it starts with www. to make a valid href | ||
| const href = res.startsWith("www.") | ||
| ? `http://${res}` |
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.
| ? `http://${res}` | |
| ? `https://${res}` |
i'm thinking we would want to add https instead of just http?
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 catch, I'll try to have this done tomorrow.
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.
We 100% want to always send to https.
| rel="noopener noreferrer" | ||
| className="text-blue-600 underline hover:text-blue-800" | ||
| > | ||
| {res} |
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 think it'd be best to show the punycode representation here since unicode can be misleading
Consider the following case. It looks awfully similar to apple.com, but it's not really
new URL("https://аррlе.com")
URL { href: "https://xn--l-7sbq6ba.com/", origin: "https://xn--l-7sbq6ba.com", protocol: "https:", username: "", password: "", host: "xn--l-7sbq6ba.com", hostname: "xn--l-7sbq6ba.com", port: "", pathname: "/", search: "" }
indifferentghost
left a comment
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 may have overstepped my suggestions, here's why I think this improves the code:
- It makes the second URL check more useful by helping us format values
- Parsing a URL through the URL handler ensures data integrity. We are sending a url and not an
http://prepended string.
Here's the cons of this approach:
- We're losing the
www.from the URL. - The more regex used the harder it is to follow
- Named capturing groups are relatively new, anyone using a non-standard or 7+ year old browser may have problems viewing this content.
| import { useAuthContext } from "../../contexts/AuthContext"; | ||
| import { useEventsContext } from "../../contexts/EventsContext"; | ||
|
|
||
| const URLRegex = /(https?:\/\/[^\s]+|www\.[^\s]+)/g; |
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 wondering if we can use capturing groups to better effect:
We can start by setting up capturing groups
const URLRegex = /(https?:\/\/|www\.)([^\s]+)/g;
This attempts to isolate the scheme and www subdomain from the rest of the url. The first capturing group grabs either the protocol https:// or the www. subdomain, but lacks the ability to grab both.
We can add an additional capturing group and make it optional ?.
const URLRegex = /(https?:\/\/(www.)?|www\.)([^\s]+)/g;
Our capturing groups are now a mess, so you can use a non-capturing group to clean things up.
const URLRegex = /(?:https?:\/\/(?:www.)?|www\.)([^\s]+)/g;
But even better might be giving some implicit documentation so we know what we're doing. Named capturing groups also exist.
| const URLRegex = /(https?:\/\/[^\s]+|www\.[^\s]+)/g; | |
| const URLRegex = /(https?:\/\/(www.)?|www\.)(?<host>[^\s]+)/g; |
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 is actually hard to grok just from looking at the regex. It might be worthwhile to throw some jsdoc here.
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'm a total regex noob so I wasn't sure I was going to do it right lol. I'll try to add some jsdoc once I can understand what is going on myself.
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.
When I add the new regex line the link no longer works. Did you test it yourself?
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.
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.
Weird, I'm using the latest version of Chrome. I sent you a message on Discord. If you want we can set up a time to meet on there and I can show you the problem I am having.
| const separated = children.split(URLRegex); | ||
|
|
||
| return separated.map((res, index) => { | ||
| if (URLRegex.test(res)) { |
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.
With a named capturing group we can better use our methods to get a predictable result. (I prefer ending early over gate control.
| if (URLRegex.test(res)) { | |
| const parsedUrl = URLRegex.exec(res); | |
| if (parsedUrl === null) { | |
| return res; | |
| } |
| const href = res.startsWith("www.") | ||
| ? `http://${res}` | ||
| : new URL(res).toString(); |
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.
Finally we add back the schema and parse it. host may not be the correct group name. domain may be more descriptive.
There is some consideration that our www subdomain is removed, but I think that's fine.
| const href = res.startsWith("www.") | |
| ? `http://${res}` | |
| : new URL(res).toString(); | |
| const formattedUrl = `https://${parsedUrl.groups.host}`; | |
| if (!URL.canParse(formattedUrl)) { | |
| throw new Error(`Unable to parse ${res}`); | |
| } | |
| const href = new URL(formattedUrl).toString(); |
| if (URLRegex.test(res)) { | ||
| // Prepend http:// if it starts with www. to make a valid href | ||
| const href = res.startsWith("www.") | ||
| ? `http://${res}` |
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.
We 100% want to always send to https.
| <span> | ||
| Location:{" "} | ||
| <a | ||
| href={modal.activeEvent.location} | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="text-blue-600 underline hover:text-blue-800" | ||
| > | ||
| {modal.activeEvent.location} | ||
| </a> | ||
| </span> |
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.
Is this different from the LinkText component we built?
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.
Yes, I did that part first but wasn't able to do the same thing for the event description links. Thats where you came in and recommended the LinkText component.
| <div className="description break-words w-auto min-h-20 mb-2 p-2 border-solid border-black border-2 font-semibold rounded-xl bg-neutral-200/50"> | ||
| <p>{modal.activeEvent.description}</p> | ||
| <p> | ||
| <LinkText>{modal.activeEvent.description}</LinkText> |
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 the LinkText isn't for user inserted content, we may have over-engineered, but it's okay.
| {res} | ||
| </a> | ||
| ); | ||
| } |
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.
Since our check returns res early we don't need this closing bracket.
| } |
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.
Here's the early returning check #641 (comment)
| rel="noopener noreferrer" | ||
| className="text-blue-600 underline hover:text-blue-800" | ||
| > | ||
| {res} |
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 should reference the href as display links can be deliberately misleading.
| {res} | |
| {href} |
|
@indifferentghost honestly most of that went over my head, if anyone else can weight in and let me know if those changes all make sense I'll try to implement them. |
|
i like these changes and can moderately follow this. seems like it makes sense to implement then continue the review |
|
I have gone through and made changes, making the regex also handle something like example.com as well as www.example.com and https://www.example.com. I also tried to do the punycode thing @20jasper mentioned and replaced http with https on line 24. Let me know what you think! |
| res.startsWith("http://") || res.startsWith("https://") | ||
| ? res | ||
| : res.startsWith("www.") | ||
| ? `https://${res}` | ||
| : `https://${res}`; // bare domains like google.com |
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 not sure i understand this part, could you walk me through what's happening here?
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 checks if res has a protocol of either http or https, if not it checks if it starts with www. Then if it doesn't have any of that it assumes it is a bare domain like if someone just typed google.com. This way the link will always be prepended with https.
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 just changed this to an if-then statement for better readability.
| key={index} | ||
| href={href} | ||
| target="_blank" | ||
| rel="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.
we might not need this if we have target=_blank
https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/rel/noopener
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 removed noopener but kept noreferrer
f0dbe8d to
ea6d2c7
Compare
|
|
||
| return ( | ||
| <a | ||
| key={index} |
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.
let's instead use the key={${res}-${index}} as the key value instead of the index
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.
Just updated it!
ea6d2c7 to
cddbd0b
Compare
|
ok i'll see if i can review this in the next week! |

Description
Added an anchor tag around the events location link making it clickable.
Type of change
Please select everything applicable. Please, do not delete any lines.
Issue
Checklist:
npm run testandnpm run test:e2eand all tests have passed successfully or I have included details within my PR on the failure.npm run lintand resolved any outstanding errors. Most issues can be solved by executingnpm run format