Skip to content

Commit 85d3777

Browse files
committed
feat(spx-gui): fix regex issue in preprocessInlineComponents used in MarkdownView
1 parent b26348b commit 85d3777

File tree

2 files changed

+48
-7
lines changed

2 files changed

+48
-7
lines changed

spx-gui/src/components/common/markdown-vue/MarkdownView.test.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,14 +137,26 @@ describe('preprocessInlineComponents', () => {
137137
const value = '<x-comp /> \nHello'
138138
const tagNames = ['x-comp']
139139
const result = preprocessInlineComponents(value, tagNames)
140-
expect(result).toBe('<x-comp />\n\nHello')
140+
expect(result).toBe('<x-comp /> \n\nHello')
141141
})
142142
it('should not change when not self-closing', () => {
143143
const value = '<x-comp></x-comp>\nHello'
144144
const tagNames = ['x-comp']
145145
const result = preprocessInlineComponents(value, tagNames)
146146
expect(result).toBe('<x-comp></x-comp>\nHello')
147147
})
148+
it('should separate even when a self-closing tag is preceded by text', () => {
149+
const value = 'before<x-comp />\nHello'
150+
const tagNames = ['x-comp']
151+
const result = preprocessInlineComponents(value, tagNames)
152+
expect(result).toBe('before<x-comp />\n\nHello')
153+
})
154+
it('should insert a blank line before an inline component when preceded by text', () => {
155+
const value = '<x-comp />\n<x-comp />\nHello\n<x-comp />'
156+
const tagNames = ['x-comp']
157+
const result = preprocessInlineComponents(value, tagNames)
158+
expect(result).toBe('<x-comp />\n\n<x-comp />\n\nHello\n<x-comp />')
159+
})
148160
})
149161

150162
describe('preprocessIncompleteTags', () => {

spx-gui/src/components/common/markdown-vue/MarkdownView.ts

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,12 @@ export function preprocessCustomRawComponents(value: string, tagNames: string[])
129129
return value
130130
}
131131

132+
const tagNamePattern = /<([a-zA-Z0-9-]+)(\s[^>]*)?\/>$/
133+
function getTagName(line: string): string | null {
134+
const m = line.match(tagNamePattern)
135+
return m != null ? m[1] : null
136+
}
137+
132138
/**
133139
* Preprocesses text immediately following custom self-closing elements and line breaks within a Markdown string.
134140
* According to the Markdown specification, this behavior—the custom self-closing element,
@@ -152,12 +158,35 @@ export function preprocessCustomRawComponents(value: string, tagNames: string[])
152158
* Refer to: https://github.com/goplus/builder/issues/2472
153159
*/
154160
export function preprocessInlineComponents(value: string, tagNames: string[]) {
155-
tagNames.forEach((tagName) => {
156-
// This scenario only occurs with self-closing tags, so this processing currently only targets
157-
// self-closing tags of custom elements.
158-
value = value.replace(new RegExp(`(<${tagName}[^>]*/>)[ \t]*\r?\n([^\n]*\\S[^\n]*)`, 'g'), '$1\n\n$2')
159-
})
160-
return value
161+
const tagSet = new Set(tagNames)
162+
const lines = value.split(/\r?\n/)
163+
const out: string[] = []
164+
165+
for (let i = 0; i < lines.length; i++) {
166+
const line = lines[i]
167+
const trimmed = line.trimEnd()
168+
169+
// Check if the line ends with a self-closing tag
170+
if (trimmed.endsWith('/>')) {
171+
const tag = getTagName(trimmed)
172+
if (
173+
// Tag name must be in the provided list
174+
tag != null &&
175+
tagSet.has(tag) &&
176+
// There must be a following line
177+
i + 1 < lines.length &&
178+
// The next line must NOT be a blank line
179+
lines[i + 1].trim() !== ''
180+
) {
181+
out.push(line)
182+
out.push('')
183+
continue
184+
}
185+
}
186+
out.push(line)
187+
}
188+
189+
return out.join('\n')
161190
}
162191

163192
const tagHeaderPattern = /<([a-zA-Z0-9-]+)(\s|<)/

0 commit comments

Comments
 (0)