-
Notifications
You must be signed in to change notification settings - Fork 6k
Better parsing of pasted html as markdown so agents understand #9190
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d3074ce
192cf70
943df68
f0dd93b
c855973
bc1b7ed
9f26c73
c6e3aa3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,6 +44,29 @@ import { UserInput, ImageData } from '../types/message'; | |
| import { compressImageDataUrl } from '../utils/conversionUtils'; | ||
| import { fetchCanonicalModelInfo } from '../utils/canonical'; | ||
| import { defineMessages, useIntl } from '../i18n'; | ||
| import TurndownService from 'turndown'; | ||
|
|
||
| const turndown = new TurndownService({ | ||
| headingStyle: 'atx', | ||
| bulletListMarker: '-', | ||
| codeBlockStyle: 'fenced', | ||
| }); | ||
|
|
||
| turndown.addRule('complexLinks', { | ||
| filter: (node) => { | ||
| return ( | ||
| node.nodeName === 'A' && | ||
| !!node.getAttribute('href') && | ||
| /\n/.test(node.textContent || '') | ||
| ); | ||
| }, | ||
| replacement: (content, node) => { | ||
| const el = node as HTMLElement; | ||
| const href = el.getAttribute('href')!; | ||
| const label = content.replace(/\n+/g, ' ').trim(); | ||
| return `[${label}](${href})`; | ||
| }, | ||
| }); | ||
|
|
||
| interface PastedImage { | ||
| id: string; | ||
|
|
@@ -811,10 +834,40 @@ export default function ChatInput({ | |
| }, [droppedFiles.length, localDroppedFiles.length, onFilesProcessed, setLocalDroppedFiles]); | ||
|
|
||
| const handlePaste = async (evt: React.ClipboardEvent<HTMLTextAreaElement>) => { | ||
| if (isRecording) return; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Returning immediately when Useful? React with 👍 / 👎. |
||
|
|
||
| const files = Array.from(evt.clipboardData.files || []); | ||
| const imageFiles = files.filter((file) => file.type.startsWith('image/')); | ||
|
|
||
| if (imageFiles.length === 0) return; | ||
| if (imageFiles.length === 0) { | ||
| const html = evt.clipboardData.getData('text/html'); | ||
| if (html) { | ||
| const doc = new DOMParser().parseFromString(html, 'text/html'); | ||
| const hasLinks = doc.querySelectorAll('a[href]').length > 0; | ||
| if (hasLinks) { | ||
| const markdown = turndown.turndown(doc.body).trim(); | ||
| if (markdown) { | ||
| evt.preventDefault(); | ||
| const textarea = textAreaRef.current; | ||
| if (textarea) { | ||
| const start = textarea.selectionStart; | ||
| const end = textarea.selectionEnd; | ||
| const newValue = | ||
| displayValue.substring(0, start) + markdown + displayValue.substring(end); | ||
| const cursorPos = start + markdown.length; | ||
| setDisplayValue(newValue); | ||
| updateValue(newValue); | ||
| setHasUserTyped(true); | ||
| checkForMentionOrSlash(newValue, cursorPos, textarea); | ||
| requestAnimationFrame(() => { | ||
| textarea.selectionStart = textarea.selectionEnd = cursorPos; | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| // Check if adding these images would exceed the limit | ||
| if (pastedImages.length + imageFiles.length > MAX_IMAGES_PER_MESSAGE) { | ||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
complexLinksrule builds markdown links with a rawhref([${label}](${href})), so pasted anchors whose URLs contain markdown-significant characters (for example unmatched)or whitespace) can produce malformed markdown and broken link destinations. This path is triggered specifically for multiline link text, so rich-text content from sources like docs/wiki pages can be converted into invalid links instead of preserving the original target reliably.Useful? React with 👍 / 👎.