Last active
April 10, 2024 21:17
-
-
Save javan/7b0c99f43e67080c2380e8d30707f773 to your computer and use it in GitHub Desktop.
Trix auto-linker. Demo: http://codepen.io/javan/pen/YqeQdG
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
addEventListener "trix-initialize", (event) -> | |
new TrixAutoLinker event.target | |
class TrixAutoLinker | |
constructor: (@element) -> | |
{@editor} = @element | |
@element.addEventListener("trix-render", @autoLink) | |
@autoLink() | |
autoLink: => | |
for {url, range} in @getURLsWithRanges() | |
unless @getHrefAtRange(range) is url | |
currentRange = @editor.getSelectedRange() | |
@editor.setSelectedRange(range) | |
if @editor.canActivateAttribute("href") | |
@editor.activateAttribute("href", url) | |
@editor.setSelectedRange(currentRange) | |
getDocument: -> | |
@editor.getDocument() | |
getDocumentString: -> | |
@getDocument().toString() | |
getHrefAtRange: (range) -> | |
@getDocument().getCommonAttributesAtRange(range).href | |
PATTERN = ///(https?://\S+\.\S+)\s///ig | |
getURLsWithRanges: -> | |
results = [] | |
string = @getDocumentString() | |
while match = PATTERN.exec(string) | |
url = match[1] | |
if isValidURL(url) | |
position = match.index | |
range = [position, position + url.length] | |
results.push({url, range}) | |
results | |
INPUT = document.createElement("input") | |
INPUT.type = "url" | |
INPUT.required = true | |
isValidURL = (value) -> | |
INPUT.value = value | |
INPUT.checkValidity() |
Converted this to a React hook:
import { useCallback, useEffect } from 'react';
const getHrefAtRange = (editor, range) => editor.getDocument().getCommonAttributesAtRange(range).href;
export const getURLsWithRanges = (string) => {
const results = [];
const pattern = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#/%?=~_|!:,.;]*[-A-Z0-9+&@#/%=~_|])/gi;
let match = pattern.exec(string);
while (match !== null) {
const url = match[1];
if (isValidURL(url)) {
const position = match.index;
const range = [position, position + url.length];
results.push({ url, range });
}
match = pattern.exec(string);
}
return results;
};
const isValidURL = (value) => {
const input = document.createElement('input');
input.type = 'url';
input.required = true;
input.value = value;
return input.checkValidity();
};
const useTrixAutoLinker = (trixElement) => {
useEffect(() => {
if (!trixElement) return;
trixElement.addEventListener('trix-render', autoLink);
autoLink();
// eslint-disable-next-line consistent-return
return () => {
trixElement.removeEventListener('trix-render', autoLink);
};
}, [trixElement]);
const autoLink = useCallback(() => {
setTimeout(() => {
const urlsAndRanges = getURLsWithRanges(
trixElement.editor.getDocument().toString()
);
urlsAndRanges.forEach(({ url, range }) => {
const href = getHrefAtRange(trixElement.editor, range);
if (href !== url) {
const currentRange = trixElement.editor.getSelectedRange();
trixElement.editor.setSelectedRange(range);
if (trixElement.editor.canActivateAttribute('href')) {
trixElement.editor.activateAttribute('href', url);
}
trixElement.editor.setSelectedRange(currentRange);
}
});
}, 0);
}, [trixElement, getURLsWithRanges, getHrefAtRange]);
};
export default useTrixAutoLinker;
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It's working! But currently working for the only
https
but I want to work withhttp
orwww
or.com
anyone.How to do this?
Thanks