Skip to content

Commit b4e020f

Browse files
committed
🐛 blockquote이 tag-replacement 문자만 인식하던 문제 해결
1 parent bd53164 commit b4e020f

File tree

3 files changed

+60
-45
lines changed

3 files changed

+60
-45
lines changed

src/components/SlackMarkdown/components/Blockquote.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export const Blockquote = ({ children, type }: React.PropsWithChildren<Blockquot
3636
'first:before:rounded-t-sm first:after:rounded-t-sm last:before:rounded-b-sm last:after:rounded-b-sm'
3737
)}
3838
>
39-
<span className="block h-[22px]">{children}</span>
39+
<span className="block min-h-[22px] leading-[22px]">{children}</span>
4040
</blockquote>
4141
)
4242
}

src/components/SlackMarkdown/utils/convert.ts

Lines changed: 37 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,13 @@ import {
55
emojiRegex,
66
linkWithTextRegex,
77
mentionRegex,
8+
placeholders,
9+
rawBrElement,
10+
rawNewLineElement,
811
strikeRegex,
912
} from '@/components/SlackMarkdown/utils/regex'
1013
import { objectKeys } from '@toss/utils'
1114

12-
const gtltConvertMap = {
13-
'&gt;': '>',
14-
'&lt;': '<',
15-
}
16-
1715
const replaceABrAfterTag = (text: string, tagname: string) => {
1816
return text.replace(
1917
new RegExp(`<${tagname} .*>.*</${tagname}>(${rawBrElement})`, 'g'),
@@ -36,11 +34,6 @@ export const convertMentionString = (text: string) => {
3634
})
3735
}
3836

39-
const codeBlockPlaceholder =
40-
'_____f1ae2436-495c-4cde-9396-cdca8965b295_CODEBLOCK_f1ae2436-495c-4cde-9396-cdca8965b295____'
41-
const rawNewLineElement = String.raw`<div className="h-2" />`
42-
const rawBrElement = String.raw`<br />`
43-
4437
export const convertNewLineToRawElement = (text: string) => {
4538
const convert = (t: string) => {
4639
const unifiedNewLineVariants = t.replace(/\r\n|\r|\n/g, '\n')
@@ -55,10 +48,10 @@ export const convertNewLineToRawElement = (text: string) => {
5548
return convert(text)
5649
}
5750

58-
const safeCodeBlockText = text.replace(codeBlockRegex, codeBlockPlaceholder)
51+
const safeCodeBlockText = text.replace(codeBlockRegex, placeholders.codeBlock)
5952
const convertedText = convert(safeCodeBlockText)
6053
const result = convertedText.replace(
61-
new RegExp(codeBlockPlaceholder, 'g'),
54+
new RegExp(placeholders.codeBlock, 'g'),
6255
originCodeBlockText[0]
6356
)
6457
return result
@@ -80,6 +73,11 @@ export const convertCodeBlockString = (text: string) => {
8073
}
8174

8275
export const decodeCodeBlockContent = (text: string) => {
76+
const gtltConvertMap = {
77+
'&gt;': '>',
78+
'&lt;': '<',
79+
}
80+
8381
const decoded = decodeURIComponent(text)
8482

8583
return objectKeys(gtltConvertMap).reduce((acc, key) => {
@@ -138,67 +136,62 @@ export const convertStrikeString = (text: string) => {
138136
}
139137

140138
export const convertBlockquoteString = (text: string) => {
141-
const generatePlaceholderRegex = (k: keyof typeof placeholder) => {
139+
const generatePlaceholderRegex = (k: keyof typeof placeholders.blockquote) => {
142140
const escapeRegex = (str: string) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
143-
const escapedPlaceholder = escapeRegex(placeholder[k])
141+
const escapedPlaceholder = escapeRegex(placeholders.blockquote[k])
144142
const escapedBr = escapeRegex(rawBrElement)
145143
const escapedDiv = escapeRegex(rawNewLineElement)
146-
const allEscapedPlaceholders = objectKeys(placeholder)
147-
.map((key) => escapeRegex(placeholder[key]))
144+
const allEscapedPlaceholders = objectKeys(placeholders.blockquote)
145+
.map((key) => escapeRegex(placeholders.blockquote[key].trim()))
148146
.join('|')
149147

150148
return new RegExp(
151-
`(${escapedPlaceholder}\\s+.*?)(?=${escapedBr}|${escapedDiv}|${allEscapedPlaceholders}|$)`,
152-
'g'
149+
`(${escapedPlaceholder.trim()}\\s+.*?)(?=${escapedBr}|${escapedDiv}|${allEscapedPlaceholders}|$)`,
150+
'gm'
153151
)
154152
}
155153

156-
const placeholder = {
157-
'br-once':
158-
'_____f1ae2436-495c-4cde-9396-cdca8965b295_BLOCKQUOTE-BR-ONCE_f1ae2436-495c-4cde-9396-cdca8965b295____',
159-
'br-twice':
160-
'_____f1ae2436-495c-4cde-9396-cdca8965b295_BLOCKQUOTE-BR-TWICE_f1ae2436-495c-4cde-9396-cdca8965b295____',
161-
'div-once':
162-
'_____f1ae2436-495c-4cde-9396-cdca8965b295_BLOCKQUOTE-DIV-ONCE_f1ae2436-495c-4cde-9396-cdca8965b295____',
163-
'div-twice':
164-
'_____f1ae2436-495c-4cde-9396-cdca8965b295_BLOCKQUOTE-DIV-TWICE_f1ae2436-495c-4cde-9396-cdca8965b295____',
165-
once: '_____f1ae2436-495c-4cde-9396-cdca8965b295_BLOCKQUOTE-ONCE_f1ae2436-495c-4cde-9396-cdca8965b295____',
166-
twice:
167-
'_____f1ae2436-495c-4cde-9396-cdca8965b295_BLOCKQUOTE-TWICE_f1ae2436-495c-4cde-9396-cdca8965b295____',
168-
}
169-
170154
// 반드시 replace하는 순서 고정
171155
const preConvertedText = text
172-
.replaceAll(`${rawBrElement}&gt;&gt;`, placeholder['br-twice'])
173-
.replaceAll(`${rawNewLineElement}&gt;&gt;`, placeholder['div-twice'])
174-
.replaceAll(`${rawBrElement}&gt;`, placeholder['br-once'])
175-
.replaceAll(`${rawNewLineElement}>`, placeholder['div-once'])
176-
.replace(/^&gt;&gt;/m, placeholder['twice'])
177-
.replace(/^&gt;/m, placeholder['once'])
156+
.replaceAll(
157+
new RegExp(`${rawBrElement}(&gt;|>)(&gt;|>) `, 'gm'),
158+
placeholders.blockquote['br-twice']
159+
)
160+
.replaceAll(
161+
new RegExp(`${rawNewLineElement}(&gt;|>)(&gt;|>) `, 'gm'),
162+
placeholders.blockquote['div-twice']
163+
)
164+
.replaceAll(new RegExp(`${rawBrElement}(&gt;|>) `, 'gm'), placeholders.blockquote['br-once'])
165+
.replaceAll(
166+
new RegExp(`${rawNewLineElement}(&gt;|>) `, 'gm'),
167+
placeholders.blockquote['div-once']
168+
)
169+
.replace(/^(&gt;|>)(&gt;|>) /m, placeholders.blockquote['twice'])
170+
.replace(/^(&gt;|>) /m, placeholders.blockquote['once'])
178171

179172
const blockquoted = preConvertedText
180173
.replace(generatePlaceholderRegex('br-twice'), (match) => {
181-
const content = match.replaceAll(placeholder['br-twice'], '')
174+
const content = match.replace(placeholders.blockquote['br-twice'], '')
182175
return `${rawBrElement}<blockquote data-type="twice">${content}</blockquote>`
183176
})
184177
.replace(generatePlaceholderRegex('div-twice'), (match) => {
185-
const content = match.replaceAll(placeholder['div-twice'], '')
178+
const content = match.replaceAll(placeholders.blockquote['div-twice'], '')
186179
return `${rawNewLineElement}<blockquote data-type="twice">${content}</blockquote>`
187180
})
188181
.replace(generatePlaceholderRegex('br-once'), (match) => {
189-
const content = match.replaceAll(placeholder['br-once'], '')
182+
const content = match.replaceAll(placeholders.blockquote['br-once'], '')
190183
return `${rawBrElement}<blockquote data-type="once">${content}</blockquote>`
191184
})
192185
.replace(generatePlaceholderRegex('div-once'), (match) => {
193-
const content = match.replaceAll(placeholder['div-once'], '')
186+
const content = match.replaceAll(placeholders.blockquote['div-once'], '')
194187
return `${rawNewLineElement}<blockquote data-type="once">${content}</blockquote>`
195188
})
196189
.replace(generatePlaceholderRegex('once'), (match) => {
197-
const content = match.replaceAll(placeholder['once'], '')
190+
const content = match.replaceAll(placeholders.blockquote['once'], '')
198191
return `<blockquote data-type="once">${content}</blockquote>`
199192
})
200193
.replace(generatePlaceholderRegex('twice'), (match) => {
201-
const content = match.replaceAll(placeholder['twice'], '')
194+
const content = match.replaceAll(placeholders.blockquote['twice'], '')
202195
return `<blockquote data-type="twice">${content}</blockquote>`
203196
})
204197
.replace(

src/components/SlackMarkdown/utils/regex.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,25 @@ export const mentionRegex = {
1010
single: /<(@|!)[^>]+>/g,
1111
multiple: /(<(@|!)[^>]+>\s*)+/g,
1212
}
13+
14+
export const rawNewLineElement = String.raw`<div className="h-2" />`
15+
16+
export const rawBrElement = String.raw`<br />`
17+
18+
export const placeholders = {
19+
codeBlock:
20+
'_____f1ae2436-495c-4cde-9396-cdca8965b295_CODEBLOCK_f1ae2436-495c-4cde-9396-cdca8965b295____',
21+
blockquote: {
22+
'br-once':
23+
'_____f1ae2436-495c-4cde-9396-cdca8965b295_BLOCKQUOTE-BR-ONCE_f1ae2436-495c-4cde-9396-cdca8965b295____ ',
24+
'br-twice':
25+
'_____f1ae2436-495c-4cde-9396-cdca8965b295_BLOCKQUOTE-BR-TWICE_f1ae2436-495c-4cde-9396-cdca8965b295____ ',
26+
'div-once':
27+
'_____f1ae2436-495c-4cde-9396-cdca8965b295_BLOCKQUOTE-DIV-ONCE_f1ae2436-495c-4cde-9396-cdca8965b295____ ',
28+
'div-twice':
29+
'_____f1ae2436-495c-4cde-9396-cdca8965b295_BLOCKQUOTE-DIV-TWICE_f1ae2436-495c-4cde-9396-cdca8965b295____ ',
30+
once: '_____f1ae2436-495c-4cde-9396-cdca8965b295_BLOCKQUOTE-ONCE_f1ae2436-495c-4cde-9396-cdca8965b295____ ',
31+
twice:
32+
'_____f1ae2436-495c-4cde-9396-cdca8965b295_BLOCKQUOTE-TWICE_f1ae2436-495c-4cde-9396-cdca8965b295____ ',
33+
},
34+
}

0 commit comments

Comments
 (0)