mirror of
https://github.com/langgenius/dify.git
synced 2026-09-05 08:48:10 +08:00
feat(web): make markdown form field name length configurable (#41697)
This commit is contained in:
parent
6536ffc422
commit
b0b495d243
@ -16,6 +16,8 @@ WORKFLOW_GENERATION_TIMEOUT_MS=180000
|
||||
ALLOW_INLINE_STYLES=false
|
||||
# Example: ()!*&()!*&-。.;;+=—
|
||||
MARKDOWN_FORM_FIELD_NAME_EXTRA_CHARS=
|
||||
# Maximum length of Markdown form field names.
|
||||
MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH=128
|
||||
ALLOW_UNSAFE_DATA_SCHEME=false
|
||||
MAX_TREE_DEPTH=50
|
||||
MARKETPLACE_API_URL=https://marketplace.dify.ai
|
||||
|
||||
@ -66,6 +66,8 @@ NEXT_PUBLIC_ALLOW_INLINE_STYLES=false
|
||||
# Additional literal characters allowed in Markdown form field names.
|
||||
# Example: ()!*&()!*&-。.;;+=—
|
||||
NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_EXTRA_CHARS=
|
||||
# Maximum length of Markdown form field names.
|
||||
NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH=128
|
||||
|
||||
# Allow rendering unsafe URLs which have "data:" scheme.
|
||||
NEXT_PUBLIC_ALLOW_UNSAFE_DATA_SCHEME=false
|
||||
|
||||
@ -2,6 +2,8 @@ describe('env runtime transport', () => {
|
||||
const originalAgentV2Env = process.env.NEXT_PUBLIC_ENABLE_AGENT_V2
|
||||
const originalMarkdownFormFieldNameExtraChars =
|
||||
process.env.NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_EXTRA_CHARS
|
||||
const originalMarkdownFormFieldNameMaxLength =
|
||||
process.env.NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH
|
||||
const originalTurnstileSiteKey = process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY
|
||||
|
||||
beforeEach(() => {
|
||||
@ -11,9 +13,11 @@ describe('env runtime transport', () => {
|
||||
document.body.removeAttribute('data-enable-agent-v2')
|
||||
document.body.removeAttribute('data-enable-agent-v-2')
|
||||
document.body.removeAttribute('data-markdown-form-field-name-extra-chars')
|
||||
document.body.removeAttribute('data-markdown-form-field-name-max-length')
|
||||
document.body.removeAttribute('data-turnstile-site-key')
|
||||
delete process.env.NEXT_PUBLIC_ENABLE_AGENT_V2
|
||||
delete process.env.NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_EXTRA_CHARS
|
||||
delete process.env.NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH
|
||||
delete process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY
|
||||
})
|
||||
|
||||
@ -25,6 +29,11 @@ describe('env runtime transport', () => {
|
||||
else
|
||||
process.env.NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_EXTRA_CHARS =
|
||||
originalMarkdownFormFieldNameExtraChars
|
||||
if (originalMarkdownFormFieldNameMaxLength === undefined)
|
||||
delete process.env.NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH
|
||||
else
|
||||
process.env.NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH =
|
||||
originalMarkdownFormFieldNameMaxLength
|
||||
if (originalTurnstileSiteKey === undefined) delete process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY
|
||||
else process.env.NEXT_PUBLIC_TURNSTILE_SITE_KEY = originalTurnstileSiteKey
|
||||
})
|
||||
@ -74,6 +83,34 @@ describe('env runtime transport', () => {
|
||||
expect(datasetMap['data-markdown-form-field-name-extra-chars']).toBe('()!*&()!*&-')
|
||||
})
|
||||
|
||||
it('should default the Markdown form field name maximum length to 128', async () => {
|
||||
const { env } = await import('../env')
|
||||
|
||||
expect(env.NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH).toBe(128)
|
||||
})
|
||||
|
||||
it('should read the Markdown form field name maximum length from the browser runtime dataset', async () => {
|
||||
document.body.setAttribute('data-markdown-form-field-name-max-length', '64')
|
||||
|
||||
const { env } = await import('../env')
|
||||
|
||||
expect(env.NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH).toBe(64)
|
||||
})
|
||||
|
||||
it('should emit the Markdown form field name maximum length in the server runtime dataset', async () => {
|
||||
process.env.NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH = '64'
|
||||
|
||||
vi.doMock('../utils/client', () => ({
|
||||
isClient: false,
|
||||
isServer: true,
|
||||
}))
|
||||
|
||||
const { getDatasetMap } = await import('../env')
|
||||
const datasetMap = getDatasetMap()
|
||||
|
||||
expect(datasetMap['data-markdown-form-field-name-max-length']).toBe(64)
|
||||
})
|
||||
|
||||
it('should read the Turnstile site key from the browser runtime dataset', async () => {
|
||||
document.body.setAttribute('data-turnstile-site-key', 'site-key-for-tests')
|
||||
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
import type { ComponentProps } from 'react'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import MarkdownForm from '../form'
|
||||
|
||||
vi.mock('@/app/components/base/chat/chat/context', () => ({
|
||||
useChatContext: () => ({}),
|
||||
}))
|
||||
|
||||
vi.mock('@/config', async () => {
|
||||
const actual = await vi.importActual<typeof import('@/config')>('@/config')
|
||||
return {
|
||||
...actual,
|
||||
MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH: 4,
|
||||
}
|
||||
})
|
||||
|
||||
describe('MarkdownForm field name maximum length', () => {
|
||||
it('should render a field at the configured limit and reject one above it', () => {
|
||||
const node = {
|
||||
type: 'element',
|
||||
tagName: 'form',
|
||||
properties: {},
|
||||
children: [
|
||||
{
|
||||
type: 'element',
|
||||
tagName: 'input',
|
||||
properties: {
|
||||
type: 'text',
|
||||
name: 'abcd',
|
||||
placeholder: 'within-limit',
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
type: 'element',
|
||||
tagName: 'input',
|
||||
properties: {
|
||||
type: 'text',
|
||||
name: 'abcde',
|
||||
placeholder: 'above-limit',
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
} satisfies ComponentProps<typeof MarkdownForm>['node']
|
||||
|
||||
render(<MarkdownForm node={node} />)
|
||||
|
||||
expect(screen.getByPlaceholderText('within-limit')).toBeInTheDocument()
|
||||
expect(screen.queryByPlaceholderText('above-limit')).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
@ -21,7 +21,7 @@ import {
|
||||
toDayjs,
|
||||
} from '@/app/components/base/date-and-time-picker/utils/dayjs'
|
||||
import Input from '@/app/components/base/input'
|
||||
import { MARKDOWN_FORM_FIELD_NAME_EXTRA_CHARS } from '@/config'
|
||||
import { MARKDOWN_FORM_FIELD_NAME_EXTRA_CHARS, MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH } from '@/config'
|
||||
import { getMarkdownButtonAppearance } from './button-appearance'
|
||||
|
||||
const DATA_FORMAT = {
|
||||
@ -66,7 +66,12 @@ const EXTRA_SAFE_NAME_CHARS = new Set(MARKDOWN_FORM_FIELD_NAME_EXTRA_CHARS)
|
||||
const PROTOTYPE_POISON_KEYS = new Set(['__proto__', 'constructor', 'prototype'])
|
||||
|
||||
function isSafeName(name: unknown): name is string {
|
||||
if (typeof name !== 'string' || name.length === 0 || name.length > 128) return false
|
||||
if (
|
||||
typeof name !== 'string' ||
|
||||
name.length === 0 ||
|
||||
name.length > MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH
|
||||
)
|
||||
return false
|
||||
|
||||
const [firstChar, ...remainingChars] = Array.from(name)
|
||||
return (
|
||||
|
||||
@ -271,6 +271,8 @@ export const MAX_ITERATIONS_NUM = env.NEXT_PUBLIC_MAX_ITERATIONS_NUM
|
||||
export const MAX_TREE_DEPTH = env.NEXT_PUBLIC_MAX_TREE_DEPTH
|
||||
export const MARKDOWN_FORM_FIELD_NAME_EXTRA_CHARS =
|
||||
env.NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_EXTRA_CHARS
|
||||
export const MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH =
|
||||
env.NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH
|
||||
|
||||
export const ALLOW_INLINE_STYLES = env.NEXT_PUBLIC_ALLOW_INLINE_STYLES
|
||||
export const ALLOW_UNSAFE_DATA_SCHEME = env.NEXT_PUBLIC_ALLOW_UNSAFE_DATA_SCHEME
|
||||
|
||||
@ -36,6 +36,7 @@ export NEXT_PUBLIC_CSP_WHITELIST=${CSP_WHITELIST}
|
||||
export NEXT_PUBLIC_ALLOW_EMBED=${ALLOW_EMBED}
|
||||
export NEXT_PUBLIC_ALLOW_INLINE_STYLES=${ALLOW_INLINE_STYLES:-false}
|
||||
export NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_EXTRA_CHARS="${NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_EXTRA_CHARS:-${MARKDOWN_FORM_FIELD_NAME_EXTRA_CHARS:-}}"
|
||||
export NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH="${NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH:-${MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH:-}}"
|
||||
export NEXT_PUBLIC_ALLOW_UNSAFE_DATA_SCHEME=${ALLOW_UNSAFE_DATA_SCHEME:-false}
|
||||
export NEXT_PUBLIC_TOP_K_MAX_VALUE=${TOP_K_MAX_VALUE}
|
||||
export NEXT_PUBLIC_INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH=${INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH}
|
||||
|
||||
@ -100,6 +100,10 @@ const clientSchema = {
|
||||
* Additional literal characters allowed in Markdown form field names.
|
||||
*/
|
||||
NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_EXTRA_CHARS: z.string().default(''),
|
||||
/**
|
||||
* Maximum length of Markdown form field names.
|
||||
*/
|
||||
NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH: coercedNumber.default(128),
|
||||
/**
|
||||
* The API PREFIX for MARKETPLACE
|
||||
*/
|
||||
@ -260,6 +264,9 @@ export const env = createEnv({
|
||||
NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_EXTRA_CHARS: isServer
|
||||
? process.env.NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_EXTRA_CHARS
|
||||
: getRuntimeEnvFromBody('markdownFormFieldNameExtraChars'),
|
||||
NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH: isServer
|
||||
? process.env.NEXT_PUBLIC_MARKDOWN_FORM_FIELD_NAME_MAX_LENGTH
|
||||
: getRuntimeEnvFromBody('markdownFormFieldNameMaxLength'),
|
||||
NEXT_PUBLIC_MARKETPLACE_API_PREFIX: isServer
|
||||
? process.env.NEXT_PUBLIC_MARKETPLACE_API_PREFIX
|
||||
: getRuntimeEnvFromBody('marketplaceApiPrefix'),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user