diff --git a/nx-dev/feature-ai/src/lib/feed/feed-answer.tsx b/nx-dev/feature-ai/src/lib/feed/feed-answer.tsx index 9ede178fee62c3..da3a6644425280 100644 --- a/nx-dev/feature-ai/src/lib/feed/feed-answer.tsx +++ b/nx-dev/feature-ai/src/lib/feed/feed-answer.tsx @@ -11,6 +11,38 @@ import { renderMarkdown } from '@nx/nx-dev/ui-markdoc'; const callout: string = '{% callout type="warning" title="Always double-check!" %}The results may not be accurate, so please always double check with our documentation.{% /callout %}\n'; +// Rehype plugin to always open links in a new tab so we don't lose chat history. +interface RehypeNode { + type: string; + tagName?: string; + properties?: Record; + children?: RehypeNode[]; + value?: string; +} +function openLinksInNewTab() { + function walk(node: RehypeNode, callback: (node: RehypeNode) => void): void { + callback(node); + if (node.children?.length) { + node.children.forEach((child) => walk(child, callback)); + } + } + + return (tree: RehypeNode) => { + walk(tree, (node) => { + if (node.type === 'element' && node.tagName === 'a') { + console.log(node); + const props = node.properties ?? {}; + const href = props?.['href'] as string; + props.target = '_blank'; + if (href && !href.startsWith('https://nx.dev')) { + // For external links, prevent window.opener attacks. + props.rel = 'noopener noreferrer'; + } + } + }); + }; +} + export function FeedAnswer({ content, feedbackButtonCallback, @@ -63,7 +95,10 @@ export function FeedAnswer({
{!isFirst && renderMarkdown(callout, { filePath: '' }).node} - +
{!isFirst && (
diff --git a/nx-dev/feature-ai/src/lib/prompt.tsx b/nx-dev/feature-ai/src/lib/prompt.tsx index 48ccd2ac9e3b5d..76d2f5f6d97dbe 100644 --- a/nx-dev/feature-ai/src/lib/prompt.tsx +++ b/nx-dev/feature-ai/src/lib/prompt.tsx @@ -2,6 +2,7 @@ import { ChangeEvent, FormEvent, useEffect, useRef } from 'react'; import { ArrowPathIcon, PaperAirplaneIcon, + XMarkIcon, PlusIcon, StopIcon, } from '@heroicons/react/24/outline'; @@ -87,8 +88,8 @@ export function Prompt({ className={cx('bg-white dark:bg-slate-900')} onClick={handleNewChat} > -