본문 링크 삽입 시 [[ ]] 을 붙혀주고 있는데, 이걸 작성자에게 붙히도록 하지 않고 렌더링 시 http | https | www 로 시작하는 문자를 정규표현식을 이용하여 [[ 주소 ]]를 붙혀주도록 함
이 때 기존의 사용되던 [[ 링크 ]] 텍스트가 있다면 변환되지 않도록 하였음
/**
* https://abc.co.kr/@abc/4
* https://votogether.com/
* http://localhost:3000/posts/100035
* http://votogether.com/
* (?<!\[\[) 는 앞에 [[로 시작하는 지 여부를 확인한다
* https?:\/\/는 http:// 혹은 https:// 로 시작하는 지 여부를 확인한다.
* (?!\]\]) 는 뒤에 ]]로 끝나는 지 여부를 확인한다.
* [^\s] 는 공백이 아닌 문자인지 여부를 확인한다.
*/
const httpsOrHttpRegex = /(?<!\[\[)(https?:\/\/[^\s]+)(?!\]\])/g;
/**
* www.naver.com
* www.tistory.com
* (?<!\[\[) 는 앞에 [[로 시작하는 지 여부를 확인한다
* (?<!\/)는 앞에 /로 시작하는 지 여부를 확인한다. https://www 에서 www 앞에 /가 있기에 중복되어 확인하는 것을 방지하기 위함
* \b(w{3})\b 는 www로 시작하는 지 여부를 정확히 확인한다. w가 4개인 경우 판별하지 않음
* [^\s] 는 공백이 아닌 문자인지 여부를 확인한다.
* (?!\]\]) 는 뒤에 ]]로 끝나는 지 여부를 확인한다.
*/
const wwwRegex = /(?<!\[\[)(?<!\/)\b(w{3})\b[^\s]+(?!\]\])/g;
export const convertTextToUrl = (text: string) => {
const httpOrHttpsConvertedText = text.replace(httpsOrHttpRegex, url => `[[${url}]]`);
const wwwConvertedText = httpOrHttpsConvertedText.replace(wwwRegex, url => `[[${url}]]`);
return wwwConvertedText;
};
import { convertTextToUrl } from '@utils/post/convertTextToUrl';
test.each([
['www.naver.com 이걸 어째', '[[www.naver.com]] 이걸 어째'],
[
'반갑다 https://github.com/woowacourse-teams/2023-votogether/issues/703 임',
'반갑다 [[https://github.com/woowacourse-teams/2023-votogether/issues/703]] 임',
],
['안녕 wwwww.naver.com', '안녕 wwwww.naver.com'],
['http://localhost:3000/ 피카츄', '[[http://localhost:3000/]] 피카츄'],
[
'http://localhost:3000/http://localhost:3000/ 피카츄',
'[[http://localhost:3000/http://localhost:3000/]] 피카츄',
],
['www.naver.com', '[[www.naver.com]]'],
['[[www.naver.com]] www.naver.com', '[[www.naver.com]] [[www.naver.com]]'],
[
'[[http://localhost:3000/]] http://localhost:3000/',
'[[http://localhost:3000/]] [[http://localhost:3000/]]',
],
[
'[[https://votogether.com/ranking]] https://www.naver.com/',
'[[https://votogether.com/ranking]] [[https://www.naver.com/]]',
],
[
'www.naver.com www.naver.com www.naver.com https://www.npmjs.com/package/dotenv-webpack',
'[[www.naver.com]] [[www.naver.com]] [[www.naver.com]] [[https://www.npmjs.com/package/dotenv-webpack]]',
],
])(
'convertTextToUrl 함수에서 링크가 포함된 문자를 입력했을 때 문자에서 링크는 [[]]로 감싸서 반환한다.',
(word, expectedWord) => {
const result = convertTextToUrl(word);
expect(result).toBe(expectedWord);
}
);
convertTextToElement.tsx
import { MouseEvent } from 'react';
import { convertTextToUrl } from './convertTextToUrl';
export const convertTextToElement = (text: string) => {
const convertedUrlText = convertTextToUrl(text);
const linkPattern = /\[\[([^[\]]+)\]\]/g;
const parts = convertedUrlText.split(linkPattern);
const elementList = parts.map((part, index) => {
if (index % 2 === 1) {
// 링크
const linkText = part;
const linkUrl = linkText.startsWith('http' || 'https') ? linkText : `https://${linkText}`;
return (
<a
onClick={(event: MouseEvent<HTMLAnchorElement>) => {
event.stopPropagation();
}}
key={index}
href={linkUrl}
target="_blank"
style={{ textDecoration: 'underline', color: '#004EC5' }}
rel="noreferrer noopener"
>
{linkText}
</a>
);
}
// 링크가 아닌 문자열
return <span key={index}>{part}</span>;
});
return elementList;
};
<S.Content>
{convertTextToElement(content)}
</S.Content>
? <와 같은 문법을 safari에서는 최근에서야 지원을 하기 시작해서 업데이트를 하지 않은 safari에서는 사이트가 보이지 않게 됩니다.
'사용자에게 책임을 전가하지 않는다' 라는 철학이 느껴지네요!
마지막에 사파리까지 호환성 체크하신 점이 정말 꼼꼼하구요.
에디터 직접 만들어서 배포해봐도 재밌겠는걸요?😆
-제로-