@gendive/chatllm 0.6.1 → 0.6.3

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.
@@ -1770,13 +1770,16 @@ var LinkChip = ({
1770
1770
 
1771
1771
  // src/react/components/MarkdownRenderer.tsx
1772
1772
  import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1773
- var LINK_REGEX = /\[([^\]]+)\]\(([^)]+)\)/g;
1773
+ var IMAGE_REGEX = /!\[([^\]]*)\]\(([^)]+)\)/g;
1774
+ var LINK_REGEX = /(?<!!)\[([^\]]+)\]\(([^)]+)\)/g;
1774
1775
  var SOURCE_LINKS_REGEX = /(\*{0,2}출처:?\*{0,2}\s*)?((?:\[`?[^\]]+`?\]\([^)]+\)\s*)+)/gi;
1775
1776
  var CODE_BLOCK_REGEX = /```(\w*)\n?([\s\S]*?)```/g;
1776
1777
  var INLINE_CODE_REGEX = /`([^`]+)`/g;
1777
1778
  var BOLD_REGEX = /\*\*([^*]+)\*\*/g;
1778
1779
  var ITALIC_REGEX = /(?<!\*)\*([^*]+)\*(?!\*)/g;
1779
1780
  var HR_REGEX = /^---+$/gm;
1781
+ var TABLE_ROW_REGEX = /^\|(.+)\|$/;
1782
+ var TABLE_SEPARATOR_REGEX = /^\|[\s\-:|]+\|$/;
1780
1783
  var parseSourceLinks = (text) => {
1781
1784
  const links = [];
1782
1785
  let match;
@@ -1796,8 +1799,9 @@ var parseInlineElements = (text, key) => {
1796
1799
  currentText = currentText.replace(INLINE_CODE_REGEX, "\xA7CODE\xA7$1\xA7/CODE\xA7");
1797
1800
  currentText = currentText.replace(BOLD_REGEX, "\xA7BOLD\xA7$1\xA7/BOLD\xA7");
1798
1801
  currentText = currentText.replace(ITALIC_REGEX, "\xA7ITALIC\xA7$1\xA7/ITALIC\xA7");
1802
+ currentText = currentText.replace(IMAGE_REGEX, "\xA7IMAGE\xA7$1\xA7URL\xA7$2\xA7/IMAGE\xA7");
1799
1803
  currentText = currentText.replace(LINK_REGEX, "\xA7LINK\xA7$1\xA7URL\xA7$2\xA7/LINK\xA7");
1800
- const parts = currentText.split(/(§CODE§.*?§\/CODE§|§BOLD§.*?§\/BOLD§|§ITALIC§.*?§\/ITALIC§|§LINK§.*?§\/LINK§)/);
1804
+ const parts = currentText.split(/(§CODE§.*?§\/CODE§|§BOLD§.*?§\/BOLD§|§ITALIC§.*?§\/ITALIC§|§IMAGE§.*?§\/IMAGE§|§LINK§.*?§\/LINK§)/);
1801
1805
  parts.forEach((part, index) => {
1802
1806
  if (part.startsWith("\xA7CODE\xA7")) {
1803
1807
  const content = part.replace("\xA7CODE\xA7", "").replace("\xA7/CODE\xA7", "");
@@ -1824,6 +1828,28 @@ var parseInlineElements = (text, key) => {
1824
1828
  } else if (part.startsWith("\xA7ITALIC\xA7")) {
1825
1829
  const content = part.replace("\xA7ITALIC\xA7", "").replace("\xA7/ITALIC\xA7", "");
1826
1830
  elements.push(/* @__PURE__ */ jsx6("em", { children: content }, `${key}-italic-${index}`));
1831
+ } else if (part.startsWith("\xA7IMAGE\xA7")) {
1832
+ const match = part.match(/§IMAGE§(.*)§URL§(.+?)§\/IMAGE§/);
1833
+ if (match) {
1834
+ elements.push(
1835
+ /* @__PURE__ */ jsx6(
1836
+ "img",
1837
+ {
1838
+ src: match[2],
1839
+ alt: match[1] || "",
1840
+ className: "chatllm-image",
1841
+ style: {
1842
+ maxWidth: "100%",
1843
+ borderRadius: "8px",
1844
+ margin: "8px 0",
1845
+ display: "block"
1846
+ },
1847
+ loading: "lazy"
1848
+ },
1849
+ `${key}-image-${index}`
1850
+ )
1851
+ );
1852
+ }
1827
1853
  } else if (part.startsWith("\xA7LINK\xA7")) {
1828
1854
  const match = part.match(/§LINK§(.+?)§URL§(.+?)§\/LINK§/);
1829
1855
  if (match) {
@@ -1850,6 +1876,64 @@ var parseInlineElements = (text, key) => {
1850
1876
  });
1851
1877
  return elements;
1852
1878
  };
1879
+ var parseTableAlignment = (separatorRow) => {
1880
+ const cells = separatorRow.split("|").filter((cell) => cell.trim() !== "");
1881
+ return cells.map((cell) => {
1882
+ const trimmed = cell.trim();
1883
+ const hasLeftColon = trimmed.startsWith(":");
1884
+ const hasRightColon = trimmed.endsWith(":");
1885
+ if (hasLeftColon && hasRightColon) return "center";
1886
+ if (hasRightColon) return "right";
1887
+ return "left";
1888
+ });
1889
+ };
1890
+ var parseTableRow = (row) => {
1891
+ return row.split("|").slice(1, -1).map((cell) => cell.trim());
1892
+ };
1893
+ var MarkdownTable = ({ data }) => {
1894
+ return /* @__PURE__ */ jsxs5(
1895
+ "table",
1896
+ {
1897
+ className: "chatllm-table",
1898
+ style: {
1899
+ width: "100%",
1900
+ borderCollapse: "collapse",
1901
+ margin: "12px 0",
1902
+ fontSize: "14px"
1903
+ },
1904
+ children: [
1905
+ /* @__PURE__ */ jsx6("thead", { children: /* @__PURE__ */ jsx6("tr", { children: data.headers.map((header, i) => /* @__PURE__ */ jsx6(
1906
+ "th",
1907
+ {
1908
+ style: {
1909
+ border: "1px solid var(--chatllm-border, #e5e7eb)",
1910
+ padding: "10px 12px",
1911
+ textAlign: data.alignments[i] || "left",
1912
+ backgroundColor: "var(--chatllm-bg-secondary, #f9fafb)",
1913
+ fontWeight: 600,
1914
+ color: "var(--chatllm-text, #374151)"
1915
+ },
1916
+ children: parseInlineElements(header, `th-${i}`)
1917
+ },
1918
+ i
1919
+ )) }) }),
1920
+ /* @__PURE__ */ jsx6("tbody", { children: data.rows.map((row, rowIndex) => /* @__PURE__ */ jsx6("tr", { children: row.map((cell, cellIndex) => /* @__PURE__ */ jsx6(
1921
+ "td",
1922
+ {
1923
+ style: {
1924
+ border: "1px solid var(--chatllm-border, #e5e7eb)",
1925
+ padding: "10px 12px",
1926
+ textAlign: data.alignments[cellIndex] || "left",
1927
+ color: "var(--chatllm-text, #374151)"
1928
+ },
1929
+ children: parseInlineElements(cell, `td-${rowIndex}-${cellIndex}`)
1930
+ },
1931
+ cellIndex
1932
+ )) }, rowIndex)) })
1933
+ ]
1934
+ }
1935
+ );
1936
+ };
1853
1937
  var CodeBlock = ({ language, code }) => {
1854
1938
  const [copied, setCopied] = React4.useState(false);
1855
1939
  const handleCopy = async () => {
@@ -1987,6 +2071,35 @@ var MarkdownRenderer = ({ content, className }) => {
1987
2071
  const lines = processedContent.split("\n");
1988
2072
  let currentList = null;
1989
2073
  let blockquoteLines = [];
2074
+ let tableLines = [];
2075
+ const flushTable = () => {
2076
+ if (tableLines.length >= 2) {
2077
+ const headerLine = tableLines[0];
2078
+ const separatorLine = tableLines[1];
2079
+ const dataLines = tableLines.slice(2);
2080
+ if (TABLE_SEPARATOR_REGEX.test(separatorLine)) {
2081
+ const headers = parseTableRow(headerLine);
2082
+ const alignments = parseTableAlignment(separatorLine);
2083
+ const rows = dataLines.map((line) => parseTableRow(line));
2084
+ elements.push(
2085
+ /* @__PURE__ */ jsx6(
2086
+ MarkdownTable,
2087
+ {
2088
+ data: { headers, alignments, rows }
2089
+ },
2090
+ `table-${elements.length}`
2091
+ )
2092
+ );
2093
+ } else {
2094
+ tableLines.forEach((line, i) => {
2095
+ elements.push(
2096
+ /* @__PURE__ */ jsx6("p", { style: { margin: "4px 0" }, children: parseInlineElements(line, `p-table-fallback-${i}`) }, `p-table-fallback-${elements.length}-${i}`)
2097
+ );
2098
+ });
2099
+ }
2100
+ }
2101
+ tableLines = [];
2102
+ };
1990
2103
  const flushList = () => {
1991
2104
  if (currentList) {
1992
2105
  if (currentList.type === "ul") {
@@ -2047,6 +2160,14 @@ var MarkdownRenderer = ({ content, className }) => {
2047
2160
  );
2048
2161
  return;
2049
2162
  }
2163
+ if (TABLE_ROW_REGEX.test(line)) {
2164
+ flushList();
2165
+ flushBlockquote();
2166
+ tableLines.push(line);
2167
+ return;
2168
+ } else if (tableLines.length > 0) {
2169
+ flushTable();
2170
+ }
2050
2171
  if (HR_REGEX.test(line)) {
2051
2172
  flushList();
2052
2173
  flushBlockquote();
@@ -2140,6 +2261,7 @@ var MarkdownRenderer = ({ content, className }) => {
2140
2261
  });
2141
2262
  flushList();
2142
2263
  flushBlockquote();
2264
+ flushTable();
2143
2265
  return elements;
2144
2266
  }, [content]);
2145
2267
  return /* @__PURE__ */ jsx6(
@@ -3868,6 +3990,39 @@ var injectStyles = () => {
3868
3990
  background-color: var(--chatllm-border);
3869
3991
  border-radius: 3px;
3870
3992
  }
3993
+
3994
+ .chatllm-table {
3995
+ width: 100%;
3996
+ border-collapse: collapse;
3997
+ margin: 12px 0;
3998
+ }
3999
+
4000
+ .chatllm-table th,
4001
+ .chatllm-table td {
4002
+ border: 1px solid var(--chatllm-border, #e5e7eb);
4003
+ padding: 10px 12px;
4004
+ }
4005
+
4006
+ .chatllm-table th {
4007
+ background-color: var(--chatllm-bg-secondary, #f9fafb);
4008
+ font-weight: 600;
4009
+ }
4010
+
4011
+ .chatllm-table tr:hover {
4012
+ background-color: var(--chatllm-bg-hover, #f3f4f6);
4013
+ }
4014
+
4015
+ .chatllm-image {
4016
+ max-width: 100%;
4017
+ border-radius: 8px;
4018
+ margin: 8px 0;
4019
+ display: block;
4020
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
4021
+ }
4022
+
4023
+ .chatllm-image:hover {
4024
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
4025
+ }
3871
4026
  `;
3872
4027
  document.head.appendChild(style);
3873
4028
  };