Skip to content

Commit 0363df7

Browse files
Fix prompt rendering highlight regex (#1997)
Fix #1942 and #1937 <!-- ELLIPSIS_HIDDEN --> ---- > [!IMPORTANT] > Fixes regex in `RenderPromptPart` to correctly handle overlapping text chunks, addressing issues #1942 and #1937. > > - **Behavior**: > - Fixes regex in `RenderPromptPart` in `render-text.tsx` to handle overlapping text chunks correctly. > - Stores matches and applies replacements in reverse order to maintain correct indices. > - **Misc**: > - Addresses issues #1942 and #1937. > > <sup>This description was created by </sup>[<img alt="Ellipsis" src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=BoundaryML%2Fbaml&utm_source=github&utm_medium=referral)<sup> for 82692a1. You can [customize](https://app.ellipsis.dev/BoundaryML/settings/summaries) this summary. It will automatically update as commits are pushed.</sup> <!-- ELLIPSIS_HIDDEN -->
1 parent 779450d commit 0363df7

1 file changed

Lines changed: 32 additions & 4 deletions

File tree

  • typescript/playground-common/src/shared/baml-project-panel/playground-panel/prompt-preview

typescript/playground-common/src/shared/baml-project-panel/playground-panel/prompt-preview/render-text.tsx

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,43 @@ export const RenderPromptPart: React.FC<{
4949

5050
try {
5151
let result = text
52+
// Store all matches and their replacements. We want to avoid replacing
53+
// already replaced chunks. The regex below could match parts of the <mark>
54+
// tag that we use to highlight the text, so we need to apply replacements
55+
// once we know all their locations.
56+
const replacements: { start: number; end: number; replacement: string }[] = []
57+
5258
highlightChunks.forEach((chunk) => {
5359
if (!chunk) return
5460
if (chunk.length > 30000) return
5561
const regex = new RegExp(`(${chunk.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'g')
56-
result = result.replace(
57-
regex,
58-
'<mark class="bg-yellow-100/70 text-yellow-900 dark:bg-yellow-800/30 dark:text-yellow-100 rounded-sm px-0.5">$1</mark>',
59-
)
62+
let match
63+
while ((match = regex.exec(text)) !== null) {
64+
const start = match.index
65+
const end = start + match[0].length
66+
// Check if this range overlaps with any existing replacement
67+
const hasOverlap = replacements.some(
68+
(r) => (start >= r.start && start < r.end) || (end > r.start && end <= r.end),
69+
)
70+
71+
if (!hasOverlap) {
72+
replacements.push({
73+
start,
74+
end,
75+
replacement: `<mark class="bg-yellow-100/70 text-yellow-900 dark:bg-yellow-800/30 dark:text-yellow-100 rounded-sm px-0.5">${match[0]}</mark>`,
76+
})
77+
}
78+
}
6079
})
80+
81+
// Sort replacements in reverse order to maintain correct indices
82+
replacements.sort((a, b) => b.start - a.start)
83+
84+
// Apply all replacements
85+
for (const { start, end, replacement } of replacements) {
86+
result = result.slice(0, start) + replacement + result.slice(end)
87+
}
88+
6189
return result
6290
} catch (e) {
6391
console.error('Error highlighting text', e)

0 commit comments

Comments
 (0)