Skip to content

Commit 236c43a

Browse files
author
arthosofteq
authored
Merge pull request #1936 from RedisInsight/fe/feature/RI-4318-tutorials_images
#RI-4318 tutorials images
2 parents 31a1c8e + b958636 commit 236c43a

File tree

4 files changed

+51
-22
lines changed

4 files changed

+51
-22
lines changed

redisinsight/ui/src/pages/workbench/components/enablement-area/EnablementArea/components/LazyInternalPage/LazyInternalPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ const LazyInternalPage = ({ onClose, title, path, sourcePath, manifest, manifest
6464
const { data, status } = await fetchService.get<string>(path)
6565
if (isStatusSuccessful(status)) {
6666
dispatch(setWorkbenchEASearch(search))
67-
const contentData = await formatter.format(data, { history })
67+
const contentData = await formatter.format({ data, path }, { history })
6868
setPageData((prevState) => ({ ...prevState, content: contentData }))
6969
setLoading(false)
7070
}

redisinsight/ui/src/pages/workbench/components/enablement-area/EnablementArea/utils/formatter/MarkdownToJsxString.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ import { remarkRedisCode } from '../transform/remarkRedisCode'
1111
import { remarkImage } from '../transform/remarkImage'
1212

1313
class MarkdownToJsxString implements IFormatter {
14-
format(data: any, config?: IFormatterConfig): Promise<string> {
14+
format(input: any, config?: IFormatterConfig): Promise<string> {
15+
const { data, path } = input
1516
return new Promise((resolve, reject) => {
1617
unified()
1718
.use(remarkParse)
1819
.use(remarkGfm) // support GitHub Flavored Markdown
1920
.use(remarkRedisCode) // Add custom component for Redis code block
20-
.use(remarkImage, config ? { history: config.history } : undefined) // Add custom component for Redis code block
21+
.use(remarkImage, path) // Add custom component for Redis code block
2122
.use(remarkRehype, { allowDangerousHtml: true }) // Pass raw HTML strings through.
2223
.use(rehypeLinks, config ? { history: config.history } : undefined) // Customise links
2324
.use(MarkdownToJsxString.rehypeWrapSymbols) // Wrap special symbols inside curly braces for JSX parse
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { visit } from 'unist-util-visit'
2+
import { RESOURCES_BASE_URL } from 'uiSrc/services/resourcesService'
3+
import { remarkImage } from '../transform/remarkImage'
4+
5+
jest.mock('unist-util-visit')
6+
const TUTORIAL_PATH = 'static/custom-tutorials/tutorial-id'
7+
const testCases = [
8+
{
9+
url: '../../../_images/relative.png',
10+
path: `${TUTORIAL_PATH}/lvl1/lvl2/lvl3/intro.md`,
11+
result: `${RESOURCES_BASE_URL}${TUTORIAL_PATH}/_images/relative.png`,
12+
},
13+
{
14+
url: '/../../../_images/relative.png', // NOTE: will not work in real. There is no sense to even support absolute paths
15+
path: `${TUTORIAL_PATH}/lvl1/lvl2/lvl3/intro.md`,
16+
result: `${RESOURCES_BASE_URL}_images/relative.png`,
17+
},
18+
{
19+
url: 'https://somesite.test/image.png',
20+
path: `${TUTORIAL_PATH}/lvl1/lvl2/lvl3/intro.md`,
21+
result: 'https://somesite.test/image.png',
22+
}
23+
]
24+
describe('remarkImage', () => {
25+
testCases.forEach((tc) => {
26+
it(`should return ${tc.result} for url:${tc.url}, path: ${tc.path} `, () => {
27+
const node = {
28+
url: tc.url,
29+
};
30+
31+
// mock implementation
32+
(visit as jest.Mock)
33+
.mockImplementation((_tree: any, _name: string, callback: (node: any) => void) => { callback(node) })
34+
35+
const remark = remarkImage(tc.path)
36+
remark({} as Node)
37+
expect(node).toEqual({
38+
...node,
39+
url: tc.result,
40+
})
41+
})
42+
})
43+
})
Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,11 @@
11
import { visit } from 'unist-util-visit'
2-
import { IS_ABSOLUTE_PATH } from 'uiSrc/constants/regex'
32
import { RESOURCES_BASE_URL } from 'uiSrc/services/resourcesService'
4-
import { ApiEndpoints } from 'uiSrc/constants'
5-
import { IFormatterConfig } from './formatter/formatter.interfaces'
63

7-
const getSourcelPath = (search?: string) => {
8-
switch (true) {
9-
case search?.indexOf(ApiEndpoints.GUIDES_PATH) !== -1:
10-
return 'static/guides/'
11-
case search?.indexOf(ApiEndpoints.TUTORIALS_PATH) !== -1:
12-
return 'static/tutorials/'
13-
default:
14-
return ''
15-
}
16-
}
17-
18-
const updateUrl = (url: string) => url.replace(/^\//, '')
19-
20-
export const remarkImage = (config?: IFormatterConfig): (tree: Node) => void => (tree: any) => {
21-
const sourcePath = getSourcelPath(config?.history?.location?.search)
4+
export const remarkImage = (path: string): (tree: Node) => void => (tree: any) => {
225
// Find img node in syntax tree
236
visit(tree, 'image', (node) => {
24-
node.url = IS_ABSOLUTE_PATH.test(node.url || '') ? node.url : `${RESOURCES_BASE_URL}${sourcePath}${updateUrl(node.url)}`
7+
const pathURL = new URL(path, RESOURCES_BASE_URL)
8+
const url = new URL(node.url, pathURL)
9+
node.url = url.toString()
2510
})
2611
}

0 commit comments

Comments
 (0)