Skip to content

Commit 67d3b79

Browse files
committed
check liquid in subject
1 parent eb675ca commit 67d3b79

1 file changed

Lines changed: 76 additions & 2 deletions

File tree

console/src/components/templates/CreateTemplateDrawer.tsx

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,58 @@ import { Tour } from 'antd'
3030
import { ImportExportButton } from './ImportExportButton'
3131
import { useAuth } from '../../contexts/AuthContext'
3232

33+
/**
34+
* Validates liquid template tags in a string to ensure they are properly closed
35+
* @param text - The text to validate
36+
* @returns Object with isValid boolean and error message if invalid
37+
*/
38+
const validateLiquidTags = (text: string): { isValid: boolean; error?: string } => {
39+
if (!text) return { isValid: true }
40+
41+
// Find all opening double curly braces
42+
const openingTags = text.match(/\{\{/g) || []
43+
// Find all closing double curly braces
44+
const closingTags = text.match(/\}\}/g) || []
45+
46+
if (openingTags.length !== closingTags.length) {
47+
return {
48+
isValid: false,
49+
error: `Unclosed liquid tag detected. Found ${openingTags.length} opening tags ({{) but ${closingTags.length} closing tags (}})`
50+
}
51+
}
52+
53+
// Check for proper nesting by tracking position
54+
let openCount = 0
55+
let i = 0
56+
57+
while (i < text.length - 1) {
58+
if (text.slice(i, i + 2) === '{{') {
59+
openCount++
60+
i += 2
61+
} else if (text.slice(i, i + 2) === '}}') {
62+
if (openCount === 0) {
63+
return {
64+
isValid: false,
65+
error: 'Found closing liquid tag (}}) without matching opening tag ({{)'
66+
}
67+
}
68+
openCount--
69+
i += 2
70+
} else {
71+
i++
72+
}
73+
}
74+
75+
if (openCount > 0) {
76+
return {
77+
isValid: false,
78+
error: `${openCount} liquid tag(s) not properly closed. Make sure each {{ has a matching }}`
79+
}
80+
}
81+
82+
return { isValid: true }
83+
}
84+
3385
interface CreateTemplateDrawerProps {
3486
workspace: Workspace
3587
template?: Template
@@ -572,14 +624,36 @@ export function CreateTemplateDrawer({
572624
<Form.Item
573625
name={['email', 'subject']}
574626
label="Email subject"
575-
rules={[{ required: true, type: 'string' }]}
627+
rules={[
628+
{ required: true, type: 'string' },
629+
{
630+
validator: (_, value) => {
631+
const validation = validateLiquidTags(value)
632+
if (!validation.isValid) {
633+
return Promise.reject(new Error(validation.error))
634+
}
635+
return Promise.resolve()
636+
}
637+
}
638+
]}
576639
>
577640
<Input placeholder="Templating markup allowed" />
578641
</Form.Item>
579642
<Form.Item
580643
name={['email', 'subject_preview']}
581644
label="Subject preview"
582-
rules={[{ required: true, type: 'string' }]}
645+
rules={[
646+
{ required: true, type: 'string' },
647+
{
648+
validator: (_, value) => {
649+
const validation = validateLiquidTags(value)
650+
if (!validation.isValid) {
651+
return Promise.reject(new Error(validation.error))
652+
}
653+
return Promise.resolve()
654+
}
655+
}
656+
]}
583657
>
584658
<Input placeholder="Templating markup allowed" />
585659
</Form.Item>

0 commit comments

Comments
 (0)