@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.
- package/custom-elements.json +121 -52
- package/dist/ai-assistant-response/ai-assistant-response.scss.mjs +1 -1
- package/dist/ai-chat-header/ai-chat-header.d.ts +2 -0
- package/dist/ai-chatbot/ai-chatbot-base.d.ts +1 -0
- package/dist/ai-chatbot/ai-chatbot-base.mjs +4 -0
- package/dist/ai-chatbot/ai-chatbot.d.ts +3 -0
- package/dist/ai-chatbot/ai-chatbot.mjs +1 -1
- package/dist/ai-chatbot/ai-chatbot.scss.mjs +1 -1
- package/dist/ai-chatbot/index.d.ts +1 -1
- package/dist/ai-chatbot/index.mjs +3 -1
- package/dist/ai-chatbot/markdown-stream-controller.d.ts +1 -1
- package/dist/ai-chatbot/markdown-stream-controller.mjs +1 -1
- package/dist/ai-chatbot/utils.d.ts +1 -14
- package/dist/ai-chatbot/utils.mjs +2 -24
- package/dist/ai-chatbot-launcher/ai-chatbot-launcher.mjs +1 -1
- package/dist/ai-embedded-chat/ai-embedded-chat.mjs +1 -3
- package/dist/ai-message-thread/ai-message-thread.scss.mjs +1 -1
- package/dist/ai-tool-call-indicator/ai-tool-call-indicator.d.ts +2 -1
- package/dist/ai-tool-call-indicator/ai-tool-call-indicator.mjs +8 -3
- package/dist/ai-tool-call-indicator/ai-tool-call-indicator.scss.mjs +1 -1
- package/dist/index.mjs +3 -1
- package/dist/tools/ai-data-table/ai-data-table-definition.mjs +1 -3
- package/dist/tools/ai-data-table/ai-data-table.mjs +13 -2
- package/dist/tools/ai-data-table/ai-data-table.scss.mjs +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.mjs +3 -0
- package/dist/utils/markdown.d.ts +34 -0
- package/dist/utils/markdown.mjs +45 -0
- package/package.json +1 -1
package/dist/utils/index.mjs
CHANGED
|
@@ -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
|
+
};
|