@cnt-dev/chat-ui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +202 -0
- package/LICENSE +21 -0
- package/README.md +303 -0
- package/index.d.ts +23 -0
- package/package.json +41 -0
- package/resources/chatui/.library +14 -0
- package/resources/chatui/ChatBox-dbg.js +1099 -0
- package/resources/chatui/ChatBox-dbg.js.map +1 -0
- package/resources/chatui/ChatBox.d.ts +308 -0
- package/resources/chatui/ChatBox.d.ts.map +1 -0
- package/resources/chatui/ChatBox.gen.d.ts +545 -0
- package/resources/chatui/ChatBox.js +5 -0
- package/resources/chatui/ChatBox.js.map +1 -0
- package/resources/chatui/ChatBox.ts +1153 -0
- package/resources/chatui/library-dbg.js +28 -0
- package/resources/chatui/library-dbg.js.map +1 -0
- package/resources/chatui/library-preload.js +17 -0
- package/resources/chatui/library-preload.js.map +1 -0
- package/resources/chatui/library.d.ts +3 -0
- package/resources/chatui/library.d.ts.map +1 -0
- package/resources/chatui/library.js +5 -0
- package/resources/chatui/library.js.map +1 -0
- package/resources/chatui/library.ts +30 -0
- package/resources/chatui/manifest.json +52 -0
- package/resources/chatui/markdown-dbg.js +116 -0
- package/resources/chatui/markdown-dbg.js.map +1 -0
- package/resources/chatui/markdown.d.ts +21 -0
- package/resources/chatui/markdown.d.ts.map +1 -0
- package/resources/chatui/markdown.js +5 -0
- package/resources/chatui/markdown.js.map +1 -0
- package/resources/chatui/markdown.ts +140 -0
- package/resources/chatui/messagebundle.properties +20 -0
- package/resources/chatui/messagebundle_en.properties +20 -0
- package/resources/chatui/themes/base/ChatBox.less +702 -0
- package/resources/chatui/themes/base/library-RTL.css +3 -0
- package/resources/chatui/themes/base/library-parameters.json +1 -0
- package/resources/chatui/themes/base/library.css +3 -0
- package/resources/chatui/themes/base/library.source.less +4 -0
- package/resources/chatui/themes/sap_fiori_3/library-RTL.css +3 -0
- package/resources/chatui/themes/sap_fiori_3/library-parameters.json +1 -0
- package/resources/chatui/themes/sap_fiori_3/library.css +3 -0
- package/resources/chatui/themes/sap_fiori_3/library.source.less +3 -0
- package/resources/chatui/themes/sap_fiori_3_dark/library-RTL.css +3 -0
- package/resources/chatui/themes/sap_fiori_3_dark/library-parameters.json +1 -0
- package/resources/chatui/themes/sap_fiori_3_dark/library.css +3 -0
- package/resources/chatui/themes/sap_fiori_3_dark/library.source.less +3 -0
- package/resources/chatui/themes/sap_fiori_3_hcb/library-RTL.css +3 -0
- package/resources/chatui/themes/sap_fiori_3_hcb/library-parameters.json +1 -0
- package/resources/chatui/themes/sap_fiori_3_hcb/library.css +3 -0
- package/resources/chatui/themes/sap_fiori_3_hcb/library.source.less +3 -0
- package/resources/chatui/themes/sap_fiori_3_hcw/library-RTL.css +3 -0
- package/resources/chatui/themes/sap_fiori_3_hcw/library-parameters.json +1 -0
- package/resources/chatui/themes/sap_fiori_3_hcw/library.css +3 -0
- package/resources/chatui/themes/sap_fiori_3_hcw/library.source.less +3 -0
- package/ui5.yaml +15 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","names":["sap","ui","define","escape","s","replace","inline","text","_m","label","href","parseTableRow","line","split","slice","map","cell","trim","isSeparatorRow","test","every","c","markdownToHtml","md","lines","out","inCode","codeLines","inList","inTable","flushList","push","flushTable","i","length","startsWith","join","trimmed","endsWith","next","headers","h","cells","heading","match","level","Math","min","li"],"sources":["markdown.ts"],"sourcesContent":["/*!\n * ${copyright}\n */\n\nconst escape = (s: string): string =>\n s.replace(/&/g, \"&\").replace(/</g, \"<\").replace(/>/g, \">\").replace(/\"/g, \""\");\n\nconst inline = (text: string): string =>\n escape(text)\n .replace(/`([^`]+)`/g, \"<code>$1</code>\")\n .replace(/\\*\\*(.+?)\\*\\*/g, \"<strong>$1</strong>\")\n .replace(/__(.+?)__/g, \"<strong>$1</strong>\")\n .replace(/\\*(.+?)\\*/g, \"<em>$1</em>\")\n .replace(/_(.+?)_/g, \"<em>$1</em>\")\n .replace(\n /\\[([^\\]]+)\\]\\(([^)]+)\\)/g,\n (_m: string, label: string, href: string) =>\n `<a href=\"${href}\" target=\"_blank\" rel=\"noopener\">${label}</a>`\n );\n\nconst parseTableRow = (line: string): string[] =>\n line.split(\"|\").slice(1, -1).map((cell) => cell.trim());\n\nconst isSeparatorRow = (line: string): boolean =>\n /^\\|[\\s:-]+\\|/.test(line) && parseTableRow(line).every((c) => /^:?-+:?$/.test(c));\n\n/**\n * Minimal Markdown → HTML converter used to format assistant messages.\n *\n * Supports paragraphs, headings, unordered lists, fenced code blocks,\n * pipe-tables and the usual inline formatting (bold, italic, inline code,\n * links). Output is escaped before formatting is applied, so it is safe to\n * assign the result to `innerHTML`.\n *\n * @namespace chatui\n */\nexport default function markdownToHtml(md: string): string {\n if (!md) return \"\";\n\n const lines = md.split(\"\\n\");\n const out: string[] = [];\n let inCode = false;\n let codeLines: string[] = [];\n let inList = false;\n let inTable = false;\n\n const flushList = (): void => {\n if (inList) {\n out.push(\"</ul>\");\n inList = false;\n }\n };\n const flushTable = (): void => {\n if (inTable) {\n out.push(\"</tbody></table>\");\n inTable = false;\n }\n };\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n\n if (line.startsWith(\"```\")) {\n flushList();\n flushTable();\n if (inCode) {\n out.push(`<pre><code>${escape(codeLines.join(\"\\n\"))}</code></pre>`);\n codeLines = [];\n }\n inCode = !inCode;\n continue;\n }\n if (inCode) {\n codeLines.push(line);\n continue;\n }\n\n const trimmed = line.trim();\n\n if (!inTable && trimmed.startsWith(\"|\") && trimmed.endsWith(\"|\")) {\n const next = lines[i + 1]?.trim();\n if (next && isSeparatorRow(next)) {\n flushList();\n const headers = parseTableRow(trimmed);\n out.push('<table class=\"cnetChatBox-table\"><thead><tr>');\n for (const h of headers) out.push(`<th>${inline(h)}</th>`);\n out.push(\"</tr></thead><tbody>\");\n inTable = true;\n i++;\n continue;\n }\n }\n\n if (inTable) {\n if (trimmed.startsWith(\"|\") && trimmed.endsWith(\"|\")) {\n const cells = parseTableRow(trimmed);\n out.push(\"<tr>\");\n for (const c of cells) out.push(`<td>${inline(c)}</td>`);\n out.push(\"</tr>\");\n continue;\n }\n flushTable();\n }\n\n if (!trimmed) {\n flushList();\n flushTable();\n continue;\n }\n\n const heading = trimmed.match(/^(#{1,6})\\s+(.+)$/);\n if (heading) {\n flushList();\n flushTable();\n const level = Math.min(heading[1].length, 6);\n out.push(`<h${level}>${inline(heading[2])}</h${level}>`);\n continue;\n }\n\n const li = trimmed.match(/^[-*]\\s+(.*)/);\n if (li) {\n flushTable();\n if (!inList) {\n out.push(\"<ul>\");\n inList = true;\n }\n out.push(`<li>${inline(li[1])}</li>`);\n continue;\n }\n\n flushList();\n flushTable();\n out.push(`<p>${inline(trimmed)}</p>`);\n }\n\n flushList();\n flushTable();\n if (inCode) out.push(`<pre><code>${escape(codeLines.join(\"\\n\"))}</code></pre>`);\n return out.join(\"\");\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* ${copyright}
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const escape = (s: string): string =>
|
|
6
|
+
s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
7
|
+
|
|
8
|
+
const inline = (text: string): string =>
|
|
9
|
+
escape(text)
|
|
10
|
+
.replace(/`([^`]+)`/g, "<code>$1</code>")
|
|
11
|
+
.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>")
|
|
12
|
+
.replace(/__(.+?)__/g, "<strong>$1</strong>")
|
|
13
|
+
.replace(/\*(.+?)\*/g, "<em>$1</em>")
|
|
14
|
+
.replace(/_(.+?)_/g, "<em>$1</em>")
|
|
15
|
+
.replace(
|
|
16
|
+
/\[([^\]]+)\]\(([^)]+)\)/g,
|
|
17
|
+
(_m: string, label: string, href: string) =>
|
|
18
|
+
`<a href="${href}" target="_blank" rel="noopener">${label}</a>`
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
const parseTableRow = (line: string): string[] =>
|
|
22
|
+
line.split("|").slice(1, -1).map((cell) => cell.trim());
|
|
23
|
+
|
|
24
|
+
const isSeparatorRow = (line: string): boolean =>
|
|
25
|
+
/^\|[\s:-]+\|/.test(line) && parseTableRow(line).every((c) => /^:?-+:?$/.test(c));
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Minimal Markdown → HTML converter used to format assistant messages.
|
|
29
|
+
*
|
|
30
|
+
* Supports paragraphs, headings, unordered lists, fenced code blocks,
|
|
31
|
+
* pipe-tables and the usual inline formatting (bold, italic, inline code,
|
|
32
|
+
* links). Output is escaped before formatting is applied, so it is safe to
|
|
33
|
+
* assign the result to `innerHTML`.
|
|
34
|
+
*
|
|
35
|
+
* @namespace chatui
|
|
36
|
+
*/
|
|
37
|
+
export default function markdownToHtml(md: string): string {
|
|
38
|
+
if (!md) return "";
|
|
39
|
+
|
|
40
|
+
const lines = md.split("\n");
|
|
41
|
+
const out: string[] = [];
|
|
42
|
+
let inCode = false;
|
|
43
|
+
let codeLines: string[] = [];
|
|
44
|
+
let inList = false;
|
|
45
|
+
let inTable = false;
|
|
46
|
+
|
|
47
|
+
const flushList = (): void => {
|
|
48
|
+
if (inList) {
|
|
49
|
+
out.push("</ul>");
|
|
50
|
+
inList = false;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const flushTable = (): void => {
|
|
54
|
+
if (inTable) {
|
|
55
|
+
out.push("</tbody></table>");
|
|
56
|
+
inTable = false;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
for (let i = 0; i < lines.length; i++) {
|
|
61
|
+
const line = lines[i];
|
|
62
|
+
|
|
63
|
+
if (line.startsWith("```")) {
|
|
64
|
+
flushList();
|
|
65
|
+
flushTable();
|
|
66
|
+
if (inCode) {
|
|
67
|
+
out.push(`<pre><code>${escape(codeLines.join("\n"))}</code></pre>`);
|
|
68
|
+
codeLines = [];
|
|
69
|
+
}
|
|
70
|
+
inCode = !inCode;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (inCode) {
|
|
74
|
+
codeLines.push(line);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const trimmed = line.trim();
|
|
79
|
+
|
|
80
|
+
if (!inTable && trimmed.startsWith("|") && trimmed.endsWith("|")) {
|
|
81
|
+
const next = lines[i + 1]?.trim();
|
|
82
|
+
if (next && isSeparatorRow(next)) {
|
|
83
|
+
flushList();
|
|
84
|
+
const headers = parseTableRow(trimmed);
|
|
85
|
+
out.push('<table class="cnetChatBox-table"><thead><tr>');
|
|
86
|
+
for (const h of headers) out.push(`<th>${inline(h)}</th>`);
|
|
87
|
+
out.push("</tr></thead><tbody>");
|
|
88
|
+
inTable = true;
|
|
89
|
+
i++;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (inTable) {
|
|
95
|
+
if (trimmed.startsWith("|") && trimmed.endsWith("|")) {
|
|
96
|
+
const cells = parseTableRow(trimmed);
|
|
97
|
+
out.push("<tr>");
|
|
98
|
+
for (const c of cells) out.push(`<td>${inline(c)}</td>`);
|
|
99
|
+
out.push("</tr>");
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
flushTable();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!trimmed) {
|
|
106
|
+
flushList();
|
|
107
|
+
flushTable();
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const heading = trimmed.match(/^(#{1,6})\s+(.+)$/);
|
|
112
|
+
if (heading) {
|
|
113
|
+
flushList();
|
|
114
|
+
flushTable();
|
|
115
|
+
const level = Math.min(heading[1].length, 6);
|
|
116
|
+
out.push(`<h${level}>${inline(heading[2])}</h${level}>`);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const li = trimmed.match(/^[-*]\s+(.*)/);
|
|
121
|
+
if (li) {
|
|
122
|
+
flushTable();
|
|
123
|
+
if (!inList) {
|
|
124
|
+
out.push("<ul>");
|
|
125
|
+
inList = true;
|
|
126
|
+
}
|
|
127
|
+
out.push(`<li>${inline(li[1])}</li>`);
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
flushList();
|
|
132
|
+
flushTable();
|
|
133
|
+
out.push(`<p>${inline(trimmed)}</p>`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
flushList();
|
|
137
|
+
flushTable();
|
|
138
|
+
if (inCode) out.push(`<pre><code>${escape(codeLines.join("\n"))}</code></pre>`);
|
|
139
|
+
return out.join("");
|
|
140
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Translation file of library chatui.
|
|
2
|
+
chatbox.placeholder=Nachricht schreiben...
|
|
3
|
+
chatbox.send=Senden
|
|
4
|
+
chatbox.newChat=Neuer Chat
|
|
5
|
+
chatbox.newConversation=Neue Konversation
|
|
6
|
+
chatbox.conversations=Konversationen
|
|
7
|
+
chatbox.noConversations=Noch keine Konversationen.
|
|
8
|
+
chatbox.deleteConversation=Konversation l\u00f6schen
|
|
9
|
+
chatbox.untitledConversation=Neue Konversation
|
|
10
|
+
chatbox.emptyHint=Stell mir eine Frage, um zu beginnen.
|
|
11
|
+
chatbox.copy=In Zwischenablage kopieren
|
|
12
|
+
chatbox.copied=Kopiert
|
|
13
|
+
chatbox.attach=Datei anh\u00e4ngen
|
|
14
|
+
chatbox.removeAttachment=Anhang entfernen
|
|
15
|
+
chatbox.dropHere=Dateien hier ablegen
|
|
16
|
+
chatbox.edit=Bearbeiten
|
|
17
|
+
chatbox.save=Speichern
|
|
18
|
+
chatbox.cancel=Abbrechen
|
|
19
|
+
chatbox.yesterday=Gestern
|
|
20
|
+
chatbox.youPrefix=Du:
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Translation file of library chatui (English).
|
|
2
|
+
chatbox.placeholder=Type a message...
|
|
3
|
+
chatbox.send=Send
|
|
4
|
+
chatbox.newChat=New chat
|
|
5
|
+
chatbox.newConversation=New conversation
|
|
6
|
+
chatbox.conversations=Conversations
|
|
7
|
+
chatbox.noConversations=No conversations yet.
|
|
8
|
+
chatbox.deleteConversation=Delete conversation
|
|
9
|
+
chatbox.untitledConversation=New conversation
|
|
10
|
+
chatbox.emptyHint=Ask me anything to get started.
|
|
11
|
+
chatbox.copy=Copy to clipboard
|
|
12
|
+
chatbox.copied=Copied
|
|
13
|
+
chatbox.attach=Attach file
|
|
14
|
+
chatbox.removeAttachment=Remove attachment
|
|
15
|
+
chatbox.dropHere=Drop files here
|
|
16
|
+
chatbox.edit=Edit
|
|
17
|
+
chatbox.save=Save
|
|
18
|
+
chatbox.cancel=Cancel
|
|
19
|
+
chatbox.yesterday=Yesterday
|
|
20
|
+
chatbox.youPrefix=You:
|