@tylertech/forge-ai 0.13.5 → 0.13.6

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.
Files changed (29) hide show
  1. package/custom-elements.json +121 -52
  2. package/dist/ai-assistant-response/ai-assistant-response.scss.mjs +1 -1
  3. package/dist/ai-chat-header/ai-chat-header.d.ts +2 -0
  4. package/dist/ai-chatbot/ai-chatbot-base.d.ts +1 -0
  5. package/dist/ai-chatbot/ai-chatbot-base.mjs +4 -0
  6. package/dist/ai-chatbot/ai-chatbot.d.ts +3 -0
  7. package/dist/ai-chatbot/ai-chatbot.mjs +1 -1
  8. package/dist/ai-chatbot/ai-chatbot.scss.mjs +1 -1
  9. package/dist/ai-chatbot/index.d.ts +1 -1
  10. package/dist/ai-chatbot/index.mjs +3 -1
  11. package/dist/ai-chatbot/markdown-stream-controller.d.ts +1 -1
  12. package/dist/ai-chatbot/markdown-stream-controller.mjs +1 -1
  13. package/dist/ai-chatbot/utils.d.ts +1 -14
  14. package/dist/ai-chatbot/utils.mjs +2 -24
  15. package/dist/ai-chatbot-launcher/ai-chatbot-launcher.mjs +1 -1
  16. package/dist/ai-embedded-chat/ai-embedded-chat.mjs +1 -3
  17. package/dist/ai-message-thread/ai-message-thread.scss.mjs +1 -1
  18. package/dist/ai-tool-call-indicator/ai-tool-call-indicator.d.ts +2 -1
  19. package/dist/ai-tool-call-indicator/ai-tool-call-indicator.mjs +8 -3
  20. package/dist/ai-tool-call-indicator/ai-tool-call-indicator.scss.mjs +1 -1
  21. package/dist/index.mjs +3 -1
  22. package/dist/tools/ai-data-table/ai-data-table-definition.mjs +1 -3
  23. package/dist/tools/ai-data-table/ai-data-table.mjs +13 -2
  24. package/dist/tools/ai-data-table/ai-data-table.scss.mjs +1 -1
  25. package/dist/utils/index.d.ts +1 -0
  26. package/dist/utils/index.mjs +3 -0
  27. package/dist/utils/markdown.d.ts +34 -0
  28. package/dist/utils/markdown.mjs +45 -0
  29. package/package.json +1 -1
@@ -1,6 +1,7 @@
1
1
  import { DeleteThreadController } from "./delete-thread-controller.mjs";
2
2
  import { InfiniteScrollController } from "./infinite-scroll-controller.mjs";
3
3
  import { KeyboardNavigationController } from "./keyboard-navigation-controller.mjs";
4
+ import { renderInlineMarkdown, renderMarkdown } from "./markdown.mjs";
4
5
  import { buildCSVContent, downloadCSV, escapeCSVCell, sanitizeFilename } from "./csv-utils.mjs";
5
6
  export {
6
7
  DeleteThreadController,
@@ -9,5 +10,7 @@ export {
9
10
  buildCSVContent,
10
11
  downloadCSV,
11
12
  escapeCSVCell,
13
+ renderInlineMarkdown,
14
+ renderMarkdown,
12
15
  sanitizeFilename
13
16
  };
@@ -0,0 +1,34 @@
1
+ export interface RenderMarkdownOptions {
2
+ /**
3
+ * Whether the content is still being streamed. Streaming content (the
4
+ * default) is run through markdown-completion repairs that finish partial
5
+ * syntax as tokens arrive. Complete content (e.g. finalized user messages)
6
+ * should set this to `false` so those repairs don't mangle intentional text
7
+ * such as `[text](` into incomplete-link placeholders.
8
+ */
9
+ streaming?: boolean;
10
+ }
11
+ /**
12
+ * Renders markdown content to sanitized HTML.
13
+ * Handles incomplete syntax in streaming content, and sanitizes the output to remove unsafe tags and attributes.
14
+ *
15
+ * Block-level tables and code blocks are wrapped as keyboard-focusable, labeled
16
+ * horizontal scroll containers (`role="group"` + `tabindex="0"` + `aria-label`)
17
+ * so keyboard and screen-reader users can reach and scroll overflowing content.
18
+ * The `role="group"` ensures the `aria-label` is reliably announced. The focus
19
+ * ring and scrollbar only appear when the content actually overflows (handled in CSS).
20
+ * @param content The markdown content to render.
21
+ * @param options Options for rendering, including whether the content is streaming.
22
+ * @returns The sanitized HTML string.
23
+ */
24
+ export declare function renderMarkdown(content: string, { streaming }?: RenderMarkdownOptions): string;
25
+ /**
26
+ * Renders a single line of markdown to sanitized inline HTML (no block-level
27
+ * wrapping such as `<p>`). Used where the agent may emit bare URLs/emails or
28
+ * raw `<a>` anchors that should render as clickable links, while leaving
29
+ * plain values (IDs, codes, formulas) untouched. Sanitization strips unsafe
30
+ * protocols (e.g. `javascript:`) and disallowed tags/attributes.
31
+ * @param content The markdown content to render.
32
+ * @returns The sanitized inline HTML string.
33
+ */
34
+ export declare function renderInlineMarkdown(content: string): string;
@@ -0,0 +1,45 @@
1
+ import { marked } from "marked";
2
+ import DOMPurify from "dompurify";
3
+ import remend from "remend";
4
+ const COMPLETE_CONTENT_REMEND_OPTIONS = { links: false, images: false };
5
+ const DOMPURIFY_CONFIG = {
6
+ FORBID_TAGS: ["script", "style", "iframe", "object", "embed"],
7
+ FORBID_ATTR: ["onerror", "onload", "onclick", "onmouseover"],
8
+ ADD_ATTR: ["target", "rel"]
9
+ };
10
+ DOMPurify.addHook("afterSanitizeAttributes", (node) => {
11
+ if (node.nodeName === "A") {
12
+ node.setAttribute("target", "_blank");
13
+ node.setAttribute("rel", "noreferrer noopener");
14
+ }
15
+ });
16
+ function renderMarkdown(content, { streaming = true } = {}) {
17
+ const completedMarkdown = remend(content, streaming ? void 0 : COMPLETE_CONTENT_REMEND_OPTIONS);
18
+ const renderer = new marked.Renderer();
19
+ const renderTable = renderer.table.bind(renderer);
20
+ renderer.table = (token) => `<div data-scroll-region="table" role="group" tabindex="0" aria-label="Tabular data">${renderTable(token)}</div>`;
21
+ const renderCode = renderer.code.bind(renderer);
22
+ renderer.code = (token) => renderCode(token).replace(
23
+ /^<pre/,
24
+ '<pre data-scroll-region="code" role="group" tabindex="0" aria-label="Code block"'
25
+ );
26
+ const rawHtml = marked.parse(completedMarkdown, {
27
+ async: false,
28
+ gfm: true,
29
+ breaks: true,
30
+ renderer
31
+ });
32
+ return DOMPurify.sanitize(rawHtml, DOMPURIFY_CONFIG);
33
+ }
34
+ function renderInlineMarkdown(content) {
35
+ const rawHtml = marked.parseInline(content, {
36
+ async: false,
37
+ gfm: true,
38
+ breaks: true
39
+ });
40
+ return DOMPurify.sanitize(rawHtml, DOMPURIFY_CONFIG);
41
+ }
42
+ export {
43
+ renderInlineMarkdown,
44
+ renderMarkdown
45
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tylertech/forge-ai",
3
- "version": "0.13.5",
3
+ "version": "0.13.6",
4
4
  "description": "A library of Tyler Forge™ AI chat interface web components.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Tyler Technologies, Inc.",