Skip to content

Commit b5bee96

Browse files
committed
first implementaion of marked
1 parent 0b6e13b commit b5bee96

File tree

6 files changed

+106
-85
lines changed

6 files changed

+106
-85
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@
9292
"jsonschema": "^1.4.1",
9393
"jwt-decode": "^4.0.0",
9494
"lodash": "^4.17.19",
95+
"marked": "^15.0.7",
96+
"marked-react": "^3.0.0",
9597
"monaco-editor": "^0.33.0",
9698
"monaco-yaml": "^4.0.4",
9799
"oidc-client-ts": "^3.2.0",

src/components/KymaCompanion/components/Chat/Chat.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ export const Chat = ({
246246
className="right-aligned sap-margin-end-tiny"
247247
messageChunks={message.messageChunks}
248248
isLoading={message.isLoading}
249+
disableFormatting={true}
249250
/>
250251
);
251252
})}
Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import { Link, Text } from '@ui5/webcomponents-react';
2-
import CodePanel from './CodePanel';
3-
import { segmentMarkdownText } from 'components/KymaCompanion/utils/formatMarkdown';
1+
import { Text } from '@ui5/webcomponents-react';
2+
import { formatMessage } from 'components/KymaCompanion/utils/formatMarkdown';
43
import TasksList from './TasksList';
54
import './Message.scss';
65

76
interface MessageProps {
87
className: string;
98
messageChunks: MessageChunk[];
109
isLoading: boolean;
10+
disableFormatting?: boolean;
1111
}
1212

1313
export interface MessageChunk {
@@ -31,40 +31,24 @@ export default function Message({
3131
className,
3232
messageChunks,
3333
isLoading,
34+
disableFormatting = false,
3435
}: MessageProps): JSX.Element {
3536
if (isLoading) {
3637
return <TasksList messageChunks={messageChunks} />;
3738
}
39+
const text = messageChunks.slice(-1)[0]?.data?.answer?.content;
3840

39-
const segmentedText = segmentMarkdownText(
40-
messageChunks.slice(-1)[0]?.data?.answer?.content,
41-
);
41+
let segmentedText = null;
42+
if (disableFormatting) {
43+
segmentedText = text;
44+
} else {
45+
segmentedText = formatMessage(text);
46+
}
4247

48+
console.log(messageChunks.slice(-1)[0]?.data?.answer?.content);
4349
return (
4450
<div className={'message ' + className}>
45-
{segmentedText && (
46-
<Text className="text">
47-
{segmentedText.map((segment, index) =>
48-
segment.type === 'bold' ? (
49-
<Text key={index} className="text bold">
50-
{segment.content}
51-
</Text>
52-
) : segment.type === 'code' ? (
53-
<CodePanel key={index} text={segment.content} />
54-
) : segment.type === 'highlighted' ? (
55-
<Text key={index} className="text highlighted">
56-
{segment.content}
57-
</Text>
58-
) : segment.type === 'link' ? (
59-
<Link key={index} href={segment.content.address} target="_blank">
60-
{segment.content.name}
61-
</Link>
62-
) : (
63-
segment.content
64-
),
65-
)}
66-
</Text>
67-
)}
51+
<Text className="text">{segmentedText}</Text>
6852
</div>
6953
);
7054
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import CodePanel from 'components/KymaCompanion/components/Chat/messages/CodePanel';
2+
import { Link, Text, Title } from '@ui5/webcomponents-react';
3+
import TitleLevel from '@ui5/webcomponents/dist/types/TitleLevel';
4+
5+
export const UI5Renderer = {
6+
code(tokens: string, lang: string) {
7+
return <CodePanel text={tokens} />;
8+
},
9+
10+
codespan(tokens: string) {
11+
return <Text className="text highlighted">{tokens}</Text>;
12+
},
13+
14+
strong(tokens: string) {
15+
return <Text className="text bold">{tokens}</Text>;
16+
},
17+
18+
heading(tokens: string, depth: number) {
19+
const level = `H${depth}` as TitleLevel;
20+
return (
21+
<Title level={level} size={level}>
22+
{tokens}
23+
</Title>
24+
);
25+
},
26+
link(href: string, title: string) {
27+
return (
28+
<Link href={href} target="_blank">
29+
{title}
30+
</Link>
31+
);
32+
},
33+
};

src/components/KymaCompanion/utils/formatMarkdown.ts

Lines changed: 0 additions & 56 deletions
This file was deleted.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import Markdown from 'marked-react';
2+
import { UI5Renderer } from 'components/KymaCompanion/components/Chat/messages/markedExtension';
3+
4+
export function formatCodeSegment(
5+
text: string,
6+
): { language: string | undefined; code: string } {
7+
const lines = text.split('\n');
8+
const language = lines.shift();
9+
const nonEmptyLines = lines.filter(line => line.trim() !== '');
10+
const code = nonEmptyLines.join('\n');
11+
return { language, code };
12+
}
13+
14+
export function formatMessage(text: string): JSX.Element[] {
15+
const elements: JSX.Element[] = [];
16+
let currentText: string = '';
17+
let divs = 0;
18+
let idx = 0;
19+
let codeSection: boolean = false;
20+
text.split('\n').forEach(line => {
21+
if (line.trim().startsWith('<div')) {
22+
divs += 1;
23+
if (codeSection) {
24+
return;
25+
}
26+
elements.push(MarkdownText(currentText + '\n', idx));
27+
currentText = line + '\n';
28+
codeSection = true;
29+
return;
30+
}
31+
32+
if (codeSection && line.trim().startsWith('</div>')) {
33+
divs -= 1;
34+
currentText += line;
35+
if (divs === 0) {
36+
// TODO: Will be implemented in https://github.com/kyma-project/busola/issues/3604
37+
elements.push(<>{`---\n${currentText}\n---`}</>);
38+
codeSection = false;
39+
currentText = '';
40+
}
41+
return;
42+
}
43+
currentText += line + '\n';
44+
});
45+
46+
elements.push(MarkdownText(currentText + '\n', idx));
47+
48+
return elements;
49+
}
50+
51+
function MarkdownText(text: string, idx: number): JSX.Element {
52+
return (
53+
<div id={`msg-${idx}`}>
54+
<Markdown renderer={UI5Renderer}>{text}</Markdown>
55+
</div>
56+
);
57+
}

0 commit comments

Comments
 (0)