Skip to content

Commit

Permalink
improve url handling and support uri schemes and fragments
Browse files Browse the repository at this point in the history
I'm breaking up my large pull request into smaller ones to make it easier
to test the changes.

These are only the changes in how URLs are handled.

First, there was a bug in the regex used in Utils.isUrl().
It allowed
- www.hello.world (without a protocol, resulting in www.hello.world appended relatively)
It didn't allow
- http://wwwuzzzuppp.com

Since relative links are likely being autocompleted through an API, it makes sense
that the URL regex should be expecting absolute URLs. It's been updated to do that.
It also requires the protocol, since absolute URLs should specify a protocol.

TESTING URL REGEX:
In the editor add these links.
-[ ] https://editorjs.io/ | Link should be added successfully
-[ ] auto | Clicking an autocompleted link should be work
-[ ] http://wwwuzzzuppp.com | Links that didn't work before should work
-[ ] relative-link | This should show the Invalid URL error message
-[ ] www.hello.world | Pressing enter should show the Invalid URL error message

Support for 2 URI Schemes and URL Fragments
closes editor-js#6 | mailto link support

In the same method as the URL regex - Utils.isUrl(), we also check if the url starts with
'mailto:'
'tel:'
or '#'

and then applies an appropriate regex to test the remaining URL.

The email regex uses control characters so I had to disable no-control-regex in .eslintrc

TESTING URI SCHEMES
In the editor add these links
-[ ] mailto:[email protected] | Pressing enter should add the mailto link
-[ ] tel:5555555555 | Pressing enter should add the tel link
-[ ] #hello | Pressing enter should add the url fragment to the link

The fragments should work really well with this plugin.
https://github.com/Aleksst95/header-with-anchor
  • Loading branch information
nickolasjadams committed Oct 14, 2023
1 parent b61d79e commit a63c84b
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 7 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"codex"
],
"rules": {
"jsdoc/no-undefined-types": "off"
"jsdoc/no-undefined-types": "off",
"no-control-regex": 0
}
}
1 change: 0 additions & 1 deletion src/utils/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,3 @@ export function isElement(node) {

return node && node.nodeType && node.nodeType === Node.ELEMENT_NODE;
}

6 changes: 4 additions & 2 deletions src/utils/selection.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ export class SelectionUtils {

/**
* Methods return boolean that true if selection exists on the page
*
* @returns {boolean}
*/
static get isSelectionExists() {
const selection = SelectionUtils.get();
Expand Down Expand Up @@ -208,8 +210,8 @@ export class SelectionUtils {
/**
* Set focus to contenteditable or native input element
*
* @param element - element where to set focus
* @param offset - offset of cursor
* @param {HTMLElement} element - element where to set focus
* @param {number} offset - offset of cursor
*
* @returns {DOMRect} of range
*/
Expand Down
34 changes: 31 additions & 3 deletions src/utils/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,43 @@ export class Utils {
}

/**
* Check for a valid url string
* Check for a valid url stringd
*
* @param {string} textString — string to be checked
*
* @returns {boolean}
*/
static isUrl(textString) {
const regex = /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})/;
let test;
const URISchemes = {
Mailto: 'mailto:',
Tel: 'tel:',
};
// Regex for valid urls.
// protocol:// sub.domain. tld /extra?a=b#hash
const urlRegex = /https?:\/\/(?:[a-zA-Z0-9-]+\.)+(?:[a-zA-Z0-9-]+)[^\s]*/;

return regex.test(textString);
// Check for URI fragments
if (textString.startsWith('#')) {
test = true;
// Check for URI schemes
} else if (textString.startsWith(URISchemes.Mailto)) {
// Regex for current specification for email addresses RFC 5322
const emailRegex = /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/;

textString = textString.substring(URISchemes.Mailto.length);
test = emailRegex.test(textString);
} else if (textString.startsWith(URISchemes.Tel)) {
// Regex for any phone number and flexible formatting
const telRegex = /[+]?[0-9](?:[0-9-.()])+[0-9]/;

textString = textString.substring(URISchemes.Tel.length);
test = telRegex.test(textString);
} else {
// String will contain a standard url
test = urlRegex.test(textString);
}

return test;
};
}

0 comments on commit a63c84b

Please sign in to comment.