mirror of
https://github.com/langgenius/dify.git
synced 2026-10-04 13:47:55 +08:00
+41![gemini-code-assist[bot]](/avatar/56998622369826d13ab151bc815833de5bcfacd06c957772b394602b82b65bda?size=40)

![autofix-ci[bot]](/avatar/90c1f68f2dec38933926f82cc3639064fb96506a5738419500ebeb5085083409?size=40)







Saumya Talwani
Poojan
sahil-infocusp
非法操作
Pandaaaa906
Asuka Minato
heyszt
autofix-ci[bot]
Ijas
gemini-code-assist[bot]
木之本澪
KinomotoMio
不做了睡大觉
User
Copilot
edvatar
-LAN-
Leilei
HaKu
dependabot[bot]
wangxiaolei
Varun Chawla
Stephen Zhou
yyh
yyh
tda
root
Sisyphus
Niels Kaspers
hj24
Tyson Cung
Stephen Zhou
FFXN
slegarraga
99
Br1an
L1nSn0w
Yunlu Wen
akkoaya
盐粒 Yanli
lif
weiguang li
Copilot
crazywoola
HanWenbo
Coding On Star
CodingOnStar
Stable Genius
Stable Genius
ふるい
Xiyuan Chen
f50e44b24a
Signed-off-by: edvatar <88481784+toroleapinc@users.noreply.github.com> Signed-off-by: -LAN- <laipz8200@outlook.com> Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: majiayu000 <1835304752@qq.com> Co-authored-by: Poojan <poojan@infocusp.com> Co-authored-by: sahil-infocusp <73810410+sahil-infocusp@users.noreply.github.com> Co-authored-by: 非法操作 <hjlarry@163.com> Co-authored-by: Pandaaaa906 <ye.pandaaaa906@gmail.com> Co-authored-by: Asuka Minato <i@asukaminato.eu.org> Co-authored-by: heyszt <270985384@qq.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Ijas <ijas.ahmd.ap@gmail.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: 木之本澪 <kinomotomiovo@gmail.com> Co-authored-by: KinomotoMio <200703522+KinomotoMio@users.noreply.github.com> Co-authored-by: 不做了睡大觉 <64798754+stakeswky@users.noreply.github.com> Co-authored-by: User <user@example.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: edvatar <88481784+toroleapinc@users.noreply.github.com> Co-authored-by: -LAN- <laipz8200@outlook.com> Co-authored-by: Leilei <138381132+Inlei@users.noreply.github.com> Co-authored-by: HaKu <104669497+haku-ink@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: wangxiaolei <fatelei@gmail.com> Co-authored-by: Varun Chawla <34209028+veeceey@users.noreply.github.com> Co-authored-by: Stephen Zhou <38493346+hyoban@users.noreply.github.com> Co-authored-by: yyh <yuanyouhuilyz@gmail.com> Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com> Co-authored-by: tda <95275462+tda1017@users.noreply.github.com> Co-authored-by: root <root@DESKTOP-KQLO90N> Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai> Co-authored-by: Niels Kaspers <153818647+nielskaspers@users.noreply.github.com> Co-authored-by: hj24 <mambahj24@gmail.com> Co-authored-by: Tyson Cung <45380903+tysoncung@users.noreply.github.com> Co-authored-by: Stephen Zhou <hi@hyoban.cc> Co-authored-by: FFXN <31929997+FFXN@users.noreply.github.com> Co-authored-by: slegarraga <64795732+slegarraga@users.noreply.github.com> Co-authored-by: 99 <wh2099@pm.me> Co-authored-by: Br1an <932039080@qq.com> Co-authored-by: L1nSn0w <l1nsn0w@qq.com> Co-authored-by: Yunlu Wen <yunlu.wen@dify.ai> Co-authored-by: akkoaya <151345394+akkoaya@users.noreply.github.com> Co-authored-by: 盐粒 Yanli <yanli@dify.ai> Co-authored-by: lif <1835304752@qq.com> Co-authored-by: weiguang li <codingpunk@gmail.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> Co-authored-by: HanWenbo <124024253+hwb96@users.noreply.github.com> Co-authored-by: Coding On Star <447357187@qq.com> Co-authored-by: CodingOnStar <hanxujiang@dify.com> Co-authored-by: Stable Genius <stablegenius043@gmail.com> Co-authored-by: Stable Genius <259448942+stablegenius49@users.noreply.github.com> Co-authored-by: ふるい <46769295+Echo0ff@users.noreply.github.com> Co-authored-by: Xiyuan Chen <52963600+GareArc@users.noreply.github.com>
122 lines
4.1 KiB
TypeScript
122 lines
4.1 KiB
TypeScript
import { getMarkdownImageURL, isValidUrl } from '../utils'
|
|
|
|
vi.mock('@/config', () => ({
|
|
ALLOW_UNSAFE_DATA_SCHEME: false,
|
|
MARKETPLACE_API_PREFIX: '/api/marketplace',
|
|
}))
|
|
|
|
describe('utils', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
describe('isValidUrl', () => {
|
|
it('should return true for http: URLs', () => {
|
|
expect(isValidUrl('http://example.com')).toBe(true)
|
|
})
|
|
|
|
it('should return true for https: URLs', () => {
|
|
expect(isValidUrl('https://example.com')).toBe(true)
|
|
})
|
|
|
|
it('should return true for protocol-relative URLs', () => {
|
|
expect(isValidUrl('//cdn.example.com/image.png')).toBe(true)
|
|
})
|
|
|
|
it('should return true for mailto: URLs', () => {
|
|
expect(isValidUrl('mailto:user@example.com')).toBe(true)
|
|
})
|
|
|
|
it('should return false for data: URLs when ALLOW_UNSAFE_DATA_SCHEME is false', () => {
|
|
expect(isValidUrl('data:image/png;base64,abc123')).toBe(false)
|
|
})
|
|
|
|
it('should return false for javascript: URLs', () => {
|
|
expect(isValidUrl('javascript:alert(1)')).toBe(false)
|
|
})
|
|
|
|
it('should return false for ftp: URLs', () => {
|
|
expect(isValidUrl('ftp://files.example.com')).toBe(false)
|
|
})
|
|
|
|
it('should return false for relative paths', () => {
|
|
expect(isValidUrl('/images/photo.png')).toBe(false)
|
|
})
|
|
|
|
it('should return false for empty string', () => {
|
|
expect(isValidUrl('')).toBe(false)
|
|
})
|
|
|
|
it('should return false for plain text', () => {
|
|
expect(isValidUrl('not a url')).toBe(false)
|
|
})
|
|
})
|
|
|
|
describe('isValidUrl with ALLOW_UNSAFE_DATA_SCHEME enabled', () => {
|
|
beforeEach(() => {
|
|
vi.resetModules()
|
|
vi.doMock('@/config', () => ({
|
|
ALLOW_UNSAFE_DATA_SCHEME: true,
|
|
MARKETPLACE_API_PREFIX: '/api/marketplace',
|
|
}))
|
|
})
|
|
|
|
it('should return true for data: URLs when ALLOW_UNSAFE_DATA_SCHEME is true', async () => {
|
|
const { isValidUrl: isValidUrlWithData } = await import('../utils')
|
|
expect(isValidUrlWithData('data:image/png;base64,abc123')).toBe(true)
|
|
})
|
|
})
|
|
|
|
describe('getMarkdownImageURL', () => {
|
|
it('should return the original URL when it does not match the asset regex', () => {
|
|
expect(getMarkdownImageURL('https://example.com/image.png')).toBe('https://example.com/image.png')
|
|
})
|
|
|
|
it('should transform ./_assets URL without pathname', () => {
|
|
const result = getMarkdownImageURL('./_assets/icon.png')
|
|
expect(result).toBe('/api/marketplace/plugins//_assets/icon.png')
|
|
})
|
|
|
|
it('should transform ./_assets URL with pathname', () => {
|
|
const result = getMarkdownImageURL('./_assets/icon.png', 'my-plugin/')
|
|
expect(result).toBe('/api/marketplace/plugins/my-plugin//_assets/icon.png')
|
|
})
|
|
|
|
it('should transform _assets URL without leading dot-slash', () => {
|
|
const result = getMarkdownImageURL('_assets/logo.svg')
|
|
expect(result).toBe('/api/marketplace/plugins//_assets/logo.svg')
|
|
})
|
|
|
|
it('should transform _assets URL with pathname', () => {
|
|
const result = getMarkdownImageURL('_assets/logo.svg', 'org/plugin/')
|
|
expect(result).toBe('/api/marketplace/plugins/org/plugin//_assets/logo.svg')
|
|
})
|
|
|
|
it('should not transform URLs that contain _assets in the middle', () => {
|
|
expect(getMarkdownImageURL('https://cdn.example.com/_assets/image.png'))
|
|
.toBe('https://cdn.example.com/_assets/image.png')
|
|
})
|
|
|
|
it('should use empty string for pathname when undefined', () => {
|
|
const result = getMarkdownImageURL('./_assets/test.png')
|
|
expect(result).toBe('/api/marketplace/plugins//_assets/test.png')
|
|
})
|
|
})
|
|
|
|
describe('getMarkdownImageURL with trailing slash prefix', () => {
|
|
beforeEach(() => {
|
|
vi.resetModules()
|
|
vi.doMock('@/config', () => ({
|
|
ALLOW_UNSAFE_DATA_SCHEME: false,
|
|
MARKETPLACE_API_PREFIX: '/api/marketplace/',
|
|
}))
|
|
})
|
|
|
|
it('should not add extra slash when prefix ends with slash', async () => {
|
|
const { getMarkdownImageURL: getURL } = await import('../utils')
|
|
const result = getURL('./_assets/icon.png', 'my-plugin/')
|
|
expect(result).toBe('/api/marketplace/plugins/my-plugin//_assets/icon.png')
|
|
})
|
|
})
|
|
})
|