github처럼 link를 자동으로 인식해서 link과 같은 방식으로 만들고 싶었습니다.
[link](url.com) 의 문자열이 있으면 <a className=”” href=”url.com”>link</a> 문자열로 변환하는 로직으로 구현할 것입니다.
1. []와 ()안에 있는 내용 필터링하기
-
제목
[title]정규표현식const titleRegex = /(?<=\[).*?(?=\])/g;
/(?<=\[): 이 부분은 "Positive Lookbehind"라고 부릅니다. 여기서 **(?<=\[)**는 대괄호[바로 뒤에 오는 문자열을 찾습니다. **\**는 대괄호가 정규표현식의 특별한 의미를 가지지 않도록 이스케이프합니다(즉, 문자 그대로의 대괄호를 의미합니다).
.*?: 이 부분은 가능한 한 가장 짧은 문자열을 의미합니다. **.**는 어떤 문자든지 일치시키고, **?**는 0번 이상 반복되는 가장 짧은 문자열을 찾습니다. 이는 "Lazy" 혹은 "Non-Greedy" 매칭이라고 합니다.(?=\]): 이 부분은 "Positive Lookahead"라고 부릅니다. 여기서 **(?=\])**는 대괄호]바로 앞에 오는 문자열을 찾습니다. 마찬가지로 **\**는 대괄호가 정규표현식의 특별한 의미를 가지지 않도록 이스케이프합니다./g: 이 플래그는 "Global" 검색을 의미합니다. 즉, 문자열 전체에서 일치하는 모든 패턴을 찾습니다.
-
링크
(href)정규표현식const hrefRegex = /(?<=\().*?(?=\))/g;
위 정규표현식도 제목을 찾을 때와 동일하게 positive lookbehind와 positive lookahead를 사용했습니다. []를 ()로 바꾼 것 뿐입니다.
/(?<=\(): 이 부분은 "Positive Lookbehind"라고 부릅니다. 여기서 **(?<=\()**는 소괄호(바로 뒤에 오는 문자열을 찾습니다. **\**는 소괄호가 정규표현식에서 특별한 의미를 가지지 않도록 이스케이프합니다(즉, 문자 그대로의 소괄호를 의미합니다).
.*?: 이 부분은 가능한 한 가장 짧은 문자열을 찾습니다. **.**는 어떤 문자든지 일치시킬 수 있으며, **?**는 0번 이상 반복되는 가장 짧은 문자열을 찾습니다. 이는 "Lazy" 혹은 "Non-Greedy" 매칭이라고 합니다.(?=\)): 이 부분은 "Positive Lookahead"라고 부릅니다. 여기서 **(?=\))**는 소괄호)바로 앞에 오는 문자열을 찾습니다. 마찬가지로 **\**는 소괄호가 정규표현식의 특별한 의미를 가지지 않도록 이스케이프합니다.
-
String의 match 메서드를 이용해서 title과 href에 해당하는 문자열을 필터링 해냅니다.
const title = children.match(titleRegex); const href = children.match(hrefRegex);
2. []와 ()안의 문자열로 태그 만들기
const AnchorElement = `<a href="${href}" target="_blank" class="fill px-2 py-2 ${
underline ? 'underline underline-offset-4' : ''
} ${anchorClassName}" >${title}</a>`;
3. 기존 문자열을 대체하기
-
제목 + 링크 (
[]())의 정규표현식const linkRegex = /\[(.*?)\]\((.*?)\)/g; -
2번에서 만든 태그로 제목 + 링크(
[]())를 대체하기if (title && href) { const AnchorElement = `<a href="${href}" target="_blank" class="fill px-2 py-2 ${ underline ? 'underline underline-offset-4' : '' } ${anchorClassName}" >${title}</a>`; replacedChildren = children.replace(linkRegex, AnchorElement); }
4. dangerouslySetInnerHTML속성을 이용해서 만든 문자열 형식의 태그를 JSX문법으로 변환해주기
<Element
id={id}
className={cn(underline, className)}
dangerouslySetInnerHTML={{ __html: replacedChildren }}
/>
dangerouslySetInnerHTML은 __html로 넘긴 문자열을 자식 태그로 만들어주는 속성입니다.