mirror of
https://github.com/langgenius/dify.git
synced 2026-07-24 04:58:32 +08:00
fix: support Unicode characters in form field names (#38138)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
parent
0d2084494e
commit
d2216fe181
@ -1937,6 +1937,9 @@
|
||||
"web/app/components/base/markdown-blocks/form.tsx": {
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
},
|
||||
"prefer-regex-literals": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"web/app/components/base/markdown-blocks/index.ts": {
|
||||
|
||||
@ -532,6 +532,54 @@ describe('MarkdownForm', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// Unicode letters should be valid form field names.
|
||||
describe('Unicode name support', () => {
|
||||
it('should include Unicode-named fields from all supported controls in JSON output', async () => {
|
||||
const user = userEvent.setup()
|
||||
const node = createRootNode(
|
||||
[
|
||||
createElementNode('label', { for: '用户名' }, [createTextNode('Username:')]),
|
||||
createElementNode('input', { type: 'text', name: '用户名', value: 'Alice' }),
|
||||
createElementNode('label', { for: '密码' }, [createTextNode('Password:')]),
|
||||
createElementNode('input', { type: 'password', name: '密码', value: 'secret' }),
|
||||
createElementNode('label', { for: '内容' }, [createTextNode('Content:')]),
|
||||
createElementNode('textarea', { name: '内容', value: 'Hello' }),
|
||||
createElementNode('label', { for: '日期' }, [createTextNode('Date:')]),
|
||||
createElementNode('input', { type: 'date', name: '日期', value: dayjs('2026-01-10') }),
|
||||
createElementNode('label', { for: '时间' }, [createTextNode('Time:')]),
|
||||
createElementNode('input', { type: 'time', name: '时间', value: '09:00' }),
|
||||
createElementNode('label', { for: '日期时间' }, [createTextNode('Datetime:')]),
|
||||
createElementNode('input', { type: 'datetime', name: '日期时间', value: dayjs('2026-01-10T08:30:00') }),
|
||||
createElementNode('label', { for: 'café' }, [createTextNode('Select:')]),
|
||||
createElementNode('input', { type: 'select', name: 'café', value: 'hello', dataOptions: ['hello', 'world'] }),
|
||||
createElementNode('input', { type: 'checkbox', name: '同意条款', value: true, dataTip: 'By checking this means you agreed' }),
|
||||
createElementNode('button', { dataSize: 'small', dataVariant: 'primary' }, [createTextNode('Login')]),
|
||||
],
|
||||
{ dataFormat: 'json' },
|
||||
)
|
||||
|
||||
render(<MarkdownForm node={node} />)
|
||||
|
||||
await user.click(screen.getByRole('button', { name: 'Login' }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockOnSend).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
const submittedPayload = JSON.parse(mockOnSend.mock.calls[0]![0]) as Record<string, unknown>
|
||||
expect(submittedPayload).toMatchObject({
|
||||
用户名: 'Alice',
|
||||
密码: 'secret',
|
||||
内容: 'Hello',
|
||||
日期: 'formatted-date',
|
||||
日期时间: 'formatted-datetime',
|
||||
café: 'hello',
|
||||
同意条款: true,
|
||||
})
|
||||
expect(submittedPayload).toHaveProperty('时间')
|
||||
})
|
||||
})
|
||||
|
||||
// Double-click protection: button disables after the first submit.
|
||||
describe('Double submit prevention', () => {
|
||||
it('should disable submit button after first click', async () => {
|
||||
|
||||
@ -41,7 +41,15 @@ type SupportedType = typeof SUPPORTED_TYPES[keyof typeof SUPPORTED_TYPES]
|
||||
|
||||
const SUPPORTED_TYPES_SET = new Set<string>(Object.values(SUPPORTED_TYPES))
|
||||
|
||||
const SAFE_NAME_RE = /^[a-z][\w-]*$/i
|
||||
const SAFE_NAME_RE = (() => {
|
||||
try {
|
||||
return new RegExp('^\\p{L}[\\p{L}\\p{M}\\p{N}_-]*$', 'u')
|
||||
}
|
||||
catch {
|
||||
// Fallback for browsers without Unicode property escape support.
|
||||
return /^[a-z][\w-]*$/i
|
||||
}
|
||||
})()
|
||||
const PROTOTYPE_POISON_KEYS = new Set(['__proto__', 'constructor', 'prototype'])
|
||||
|
||||
function isSafeName(name: unknown): name is string {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user