@lazyingart/agintiflow 0.8.9 → 0.8.10
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/package.json +1 -1
- package/public/app.js +204 -1
- package/public/styles.css +133 -0
package/package.json
CHANGED
package/public/app.js
CHANGED
|
@@ -1014,6 +1014,201 @@ function escapeHtml(value) {
|
|
|
1014
1014
|
);
|
|
1015
1015
|
}
|
|
1016
1016
|
|
|
1017
|
+
function safeLinkHref(value) {
|
|
1018
|
+
const raw = String(value || "").trim();
|
|
1019
|
+
try {
|
|
1020
|
+
const parsed = new URL(raw, window.location.origin);
|
|
1021
|
+
return ["http:", "https:", "mailto:"].includes(parsed.protocol) ? parsed.href : "";
|
|
1022
|
+
} catch {
|
|
1023
|
+
return "";
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
function renderInlineMarkdown(value) {
|
|
1028
|
+
const placeholders = [];
|
|
1029
|
+
const protect = (html) => {
|
|
1030
|
+
const index = placeholders.push(html) - 1;
|
|
1031
|
+
return `\u0000${index}\u0000`;
|
|
1032
|
+
};
|
|
1033
|
+
|
|
1034
|
+
let text = String(value || "");
|
|
1035
|
+
text = text.replace(/`([^`\n]+)`/g, (_match, code) => protect(`<code>${escapeHtml(code)}</code>`));
|
|
1036
|
+
text = text.replace(/\[([^\]\n]+)]\(([^)\s]+)\)/g, (_match, label, href) => {
|
|
1037
|
+
const safeHref = safeLinkHref(href);
|
|
1038
|
+
if (!safeHref) return escapeHtml(label);
|
|
1039
|
+
return protect(
|
|
1040
|
+
`<a href="${escapeHtml(safeHref)}" target="_blank" rel="noopener noreferrer">${escapeHtml(label)}</a>`
|
|
1041
|
+
);
|
|
1042
|
+
});
|
|
1043
|
+
|
|
1044
|
+
let html = escapeHtml(text);
|
|
1045
|
+
html = html
|
|
1046
|
+
.replace(/\*\*([^*\n]+)\*\*/g, "<strong>$1</strong>")
|
|
1047
|
+
.replace(/__([^_\n]+)__/g, "<strong>$1</strong>")
|
|
1048
|
+
.replace(/\*([^*\n]+)\*/g, "<em>$1</em>")
|
|
1049
|
+
.replace(/~~([^~\n]+)~~/g, "<del>$1</del>");
|
|
1050
|
+
|
|
1051
|
+
return html.replace(/\u0000(\d+)\u0000/g, (_match, index) => placeholders[Number(index)] || "");
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
function splitTableRow(line) {
|
|
1055
|
+
return String(line || "")
|
|
1056
|
+
.trim()
|
|
1057
|
+
.replace(/^\|/, "")
|
|
1058
|
+
.replace(/\|$/, "")
|
|
1059
|
+
.split("|")
|
|
1060
|
+
.map((cell) => cell.trim());
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
function isMarkdownTableSeparator(line) {
|
|
1064
|
+
return /^\s*\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)+\|?\s*$/.test(String(line || ""));
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
function renderMarkdownTable(headerLine, rows) {
|
|
1068
|
+
const headers = splitTableRow(headerLine);
|
|
1069
|
+
const bodyRows = rows.map(splitTableRow);
|
|
1070
|
+
return `
|
|
1071
|
+
<div class="markdown-table-wrap">
|
|
1072
|
+
<table>
|
|
1073
|
+
<thead>
|
|
1074
|
+
<tr>${headers.map((cell) => `<th>${renderInlineMarkdown(cell)}</th>`).join("")}</tr>
|
|
1075
|
+
</thead>
|
|
1076
|
+
<tbody>
|
|
1077
|
+
${bodyRows
|
|
1078
|
+
.map((row) => `<tr>${headers.map((_header, index) => `<td>${renderInlineMarkdown(row[index] || "")}</td>`).join("")}</tr>`)
|
|
1079
|
+
.join("")}
|
|
1080
|
+
</tbody>
|
|
1081
|
+
</table>
|
|
1082
|
+
</div>
|
|
1083
|
+
`;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
function isMarkdownBlockStart(line, nextLine = "") {
|
|
1087
|
+
const trimmed = String(line || "").trim();
|
|
1088
|
+
return (
|
|
1089
|
+
/^```/.test(trimmed) ||
|
|
1090
|
+
/^#{1,6}\s+/.test(trimmed) ||
|
|
1091
|
+
/^[-*_]{3,}$/.test(trimmed) ||
|
|
1092
|
+
/^>\s?/.test(trimmed) ||
|
|
1093
|
+
/^[-*+]\s+/.test(trimmed) ||
|
|
1094
|
+
/^\d+\.\s+/.test(trimmed) ||
|
|
1095
|
+
(trimmed.includes("|") && isMarkdownTableSeparator(nextLine))
|
|
1096
|
+
);
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
function renderMarkdown(value) {
|
|
1100
|
+
const lines = String(value || "").replace(/\r\n?/g, "\n").split("\n");
|
|
1101
|
+
const html = [];
|
|
1102
|
+
let paragraph = [];
|
|
1103
|
+
let listType = "";
|
|
1104
|
+
let listItems = [];
|
|
1105
|
+
|
|
1106
|
+
const flushParagraph = () => {
|
|
1107
|
+
if (!paragraph.length) return;
|
|
1108
|
+
html.push(`<p>${renderInlineMarkdown(paragraph.join(" ").trim())}</p>`);
|
|
1109
|
+
paragraph = [];
|
|
1110
|
+
};
|
|
1111
|
+
|
|
1112
|
+
const flushList = () => {
|
|
1113
|
+
if (!listItems.length) return;
|
|
1114
|
+
const tag = listType === "ol" ? "ol" : "ul";
|
|
1115
|
+
html.push(`<${tag}>${listItems.map((item) => `<li>${renderInlineMarkdown(item)}</li>`).join("")}</${tag}>`);
|
|
1116
|
+
listType = "";
|
|
1117
|
+
listItems = [];
|
|
1118
|
+
};
|
|
1119
|
+
|
|
1120
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
1121
|
+
const line = lines[index];
|
|
1122
|
+
const trimmed = line.trim();
|
|
1123
|
+
|
|
1124
|
+
if (!trimmed) {
|
|
1125
|
+
flushParagraph();
|
|
1126
|
+
flushList();
|
|
1127
|
+
continue;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
const fence = trimmed.match(/^```([A-Za-z0-9_-]+)?\s*$/);
|
|
1131
|
+
if (fence) {
|
|
1132
|
+
flushParagraph();
|
|
1133
|
+
flushList();
|
|
1134
|
+
const language = fence[1] || "";
|
|
1135
|
+
const code = [];
|
|
1136
|
+
index += 1;
|
|
1137
|
+
while (index < lines.length && !/^```\s*$/.test(lines[index].trim())) {
|
|
1138
|
+
code.push(lines[index]);
|
|
1139
|
+
index += 1;
|
|
1140
|
+
}
|
|
1141
|
+
html.push(
|
|
1142
|
+
`<pre class="markdown-code"><code data-language="${escapeHtml(language)}">${escapeHtml(code.join("\n"))}</code></pre>`
|
|
1143
|
+
);
|
|
1144
|
+
continue;
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
const heading = trimmed.match(/^(#{1,6})\s+(.+?)\s*#*$/);
|
|
1148
|
+
if (heading) {
|
|
1149
|
+
flushParagraph();
|
|
1150
|
+
flushList();
|
|
1151
|
+
const level = heading[1].length;
|
|
1152
|
+
html.push(`<h${level}>${renderInlineMarkdown(heading[2])}</h${level}>`);
|
|
1153
|
+
continue;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
if (/^[-*_]{3,}$/.test(trimmed)) {
|
|
1157
|
+
flushParagraph();
|
|
1158
|
+
flushList();
|
|
1159
|
+
html.push("<hr>");
|
|
1160
|
+
continue;
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
if (trimmed.includes("|") && isMarkdownTableSeparator(lines[index + 1])) {
|
|
1164
|
+
flushParagraph();
|
|
1165
|
+
flushList();
|
|
1166
|
+
const header = line;
|
|
1167
|
+
const rows = [];
|
|
1168
|
+
index += 2;
|
|
1169
|
+
while (index < lines.length && lines[index].trim().includes("|")) {
|
|
1170
|
+
rows.push(lines[index]);
|
|
1171
|
+
index += 1;
|
|
1172
|
+
}
|
|
1173
|
+
index -= 1;
|
|
1174
|
+
html.push(renderMarkdownTable(header, rows));
|
|
1175
|
+
continue;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
if (/^>\s?/.test(trimmed)) {
|
|
1179
|
+
flushParagraph();
|
|
1180
|
+
flushList();
|
|
1181
|
+
const quote = [];
|
|
1182
|
+
while (index < lines.length && /^>\s?/.test(lines[index].trim())) {
|
|
1183
|
+
quote.push(lines[index].trim().replace(/^>\s?/, ""));
|
|
1184
|
+
index += 1;
|
|
1185
|
+
}
|
|
1186
|
+
index -= 1;
|
|
1187
|
+
html.push(`<blockquote>${renderMarkdown(quote.join("\n"))}</blockquote>`);
|
|
1188
|
+
continue;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
const unordered = trimmed.match(/^[-*+]\s+(.+)$/);
|
|
1192
|
+
const ordered = trimmed.match(/^\d+\.\s+(.+)$/);
|
|
1193
|
+
if (unordered || ordered) {
|
|
1194
|
+
flushParagraph();
|
|
1195
|
+
const nextType = ordered ? "ol" : "ul";
|
|
1196
|
+
if (listType && listType !== nextType) flushList();
|
|
1197
|
+
listType = nextType;
|
|
1198
|
+
listItems.push((unordered || ordered)[1]);
|
|
1199
|
+
continue;
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
if (listItems.length) flushList();
|
|
1203
|
+
paragraph.push(trimmed);
|
|
1204
|
+
if (index + 1 >= lines.length || isMarkdownBlockStart(lines[index + 1], lines[index + 2])) flushParagraph();
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
flushParagraph();
|
|
1208
|
+
flushList();
|
|
1209
|
+
return html.join("");
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1017
1212
|
function renderChat(chatEntries) {
|
|
1018
1213
|
lastChatEntries = chatEntries || [];
|
|
1019
1214
|
|
|
@@ -1026,7 +1221,10 @@ function renderChat(chatEntries) {
|
|
|
1026
1221
|
.map((entry) => {
|
|
1027
1222
|
const role = entry.role === "assistant" ? "assistant" : "user";
|
|
1028
1223
|
const label = role === "assistant" ? t("assistantLabel") : t("youLabel");
|
|
1029
|
-
const content =
|
|
1224
|
+
const content =
|
|
1225
|
+
role === "assistant"
|
|
1226
|
+
? `<div class="markdown-body">${renderMarkdown(entry.content)}</div>`
|
|
1227
|
+
: escapeHtml(entry.content).replace(/\n/g, "<br>");
|
|
1030
1228
|
return `
|
|
1031
1229
|
<article class="chat-item ${role}">
|
|
1032
1230
|
<div class="chat-meta">${label}${entry.at ? ` · ${new Date(entry.at).toLocaleString()}` : ""}</div>
|
|
@@ -1200,6 +1398,11 @@ function renderArtifactContent(content) {
|
|
|
1200
1398
|
}
|
|
1201
1399
|
|
|
1202
1400
|
const text = typeof content.text === "string" ? content.text : "";
|
|
1401
|
+
if (content.kind === "markdown" || /markdown/i.test(content.mime || "")) {
|
|
1402
|
+
artifactViewerBodyEl.innerHTML = `<div class="artifact-markdown markdown-body">${renderMarkdown(text)}</div>`;
|
|
1403
|
+
return;
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1203
1406
|
artifactViewerBodyEl.innerHTML = `
|
|
1204
1407
|
<textarea class="artifact-editor" readonly spellcheck="false">${escapeHtml(text)}</textarea>
|
|
1205
1408
|
`;
|
package/public/styles.css
CHANGED
|
@@ -587,6 +587,139 @@ button.danger {
|
|
|
587
587
|
overflow-wrap: anywhere;
|
|
588
588
|
}
|
|
589
589
|
|
|
590
|
+
.markdown-body {
|
|
591
|
+
line-height: 1.58;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
.markdown-body > :first-child {
|
|
595
|
+
margin-top: 0;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
.markdown-body > :last-child {
|
|
599
|
+
margin-bottom: 0;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
.markdown-body h1,
|
|
603
|
+
.markdown-body h2,
|
|
604
|
+
.markdown-body h3,
|
|
605
|
+
.markdown-body h4,
|
|
606
|
+
.markdown-body h5,
|
|
607
|
+
.markdown-body h6 {
|
|
608
|
+
margin: 0.92em 0 0.42em;
|
|
609
|
+
color: var(--ink);
|
|
610
|
+
line-height: 1.15;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
.markdown-body h1 {
|
|
614
|
+
font-size: 1.38rem;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
.markdown-body h2 {
|
|
618
|
+
font-size: 1.22rem;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
.markdown-body h3 {
|
|
622
|
+
font-size: 1.08rem;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
.markdown-body p,
|
|
626
|
+
.markdown-body ul,
|
|
627
|
+
.markdown-body ol,
|
|
628
|
+
.markdown-body blockquote,
|
|
629
|
+
.markdown-body pre,
|
|
630
|
+
.markdown-table-wrap {
|
|
631
|
+
margin: 0 0 0.82em;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
.markdown-body ul,
|
|
635
|
+
.markdown-body ol {
|
|
636
|
+
padding-left: 1.35rem;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
.markdown-body li + li {
|
|
640
|
+
margin-top: 0.28em;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
.markdown-body a {
|
|
644
|
+
color: #0f766e;
|
|
645
|
+
font-weight: 800;
|
|
646
|
+
text-decoration-thickness: 0.08em;
|
|
647
|
+
text-underline-offset: 0.16em;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
.markdown-body code {
|
|
651
|
+
padding: 0.12em 0.36em;
|
|
652
|
+
border: 1px solid rgba(15, 118, 110, 0.16);
|
|
653
|
+
border-radius: 7px;
|
|
654
|
+
background: rgba(15, 23, 42, 0.06);
|
|
655
|
+
color: #0f172a;
|
|
656
|
+
font-size: 0.92em;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
.markdown-body pre {
|
|
660
|
+
max-width: 100%;
|
|
661
|
+
padding: 12px;
|
|
662
|
+
border: 1px solid rgba(15, 118, 110, 0.18);
|
|
663
|
+
border-radius: 14px;
|
|
664
|
+
background: #111827;
|
|
665
|
+
color: #f8fafc;
|
|
666
|
+
overflow: auto;
|
|
667
|
+
white-space: pre;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
.markdown-body pre code {
|
|
671
|
+
padding: 0;
|
|
672
|
+
border: 0;
|
|
673
|
+
background: transparent;
|
|
674
|
+
color: inherit;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
.markdown-body blockquote {
|
|
678
|
+
padding: 0.2rem 0 0.2rem 0.9rem;
|
|
679
|
+
border-left: 4px solid rgba(15, 118, 110, 0.32);
|
|
680
|
+
color: var(--muted);
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
.markdown-body hr {
|
|
684
|
+
height: 1px;
|
|
685
|
+
margin: 1rem 0;
|
|
686
|
+
border: 0;
|
|
687
|
+
background: var(--line);
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
.markdown-table-wrap {
|
|
691
|
+
max-width: 100%;
|
|
692
|
+
overflow: auto;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
.markdown-body table {
|
|
696
|
+
width: 100%;
|
|
697
|
+
min-width: 420px;
|
|
698
|
+
border-collapse: collapse;
|
|
699
|
+
font-size: 0.92rem;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
.markdown-body th,
|
|
703
|
+
.markdown-body td {
|
|
704
|
+
padding: 8px 10px;
|
|
705
|
+
border: 1px solid rgba(15, 118, 110, 0.16);
|
|
706
|
+
text-align: left;
|
|
707
|
+
vertical-align: top;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
.markdown-body th {
|
|
711
|
+
background: rgba(15, 118, 110, 0.08);
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
.artifact-markdown {
|
|
715
|
+
min-height: 100%;
|
|
716
|
+
padding: 14px;
|
|
717
|
+
border: 1px solid rgba(15, 118, 110, 0.14);
|
|
718
|
+
border-radius: 16px;
|
|
719
|
+
background: rgba(255, 255, 255, 0.72);
|
|
720
|
+
overflow: auto;
|
|
721
|
+
}
|
|
722
|
+
|
|
590
723
|
.chat-form {
|
|
591
724
|
display: grid;
|
|
592
725
|
gap: 8px;
|