allow keeping styler. truncate

This commit is contained in:
Tommy D. Rossi
2026-01-10 19:48:50 +01:00
parent 107155d9f2
commit b968af2c4b
2 changed files with 4283 additions and 4168 deletions
File diff suppressed because it is too large Load Diff
+42 -13
View File
@@ -1,7 +1,19 @@
import posthtml from 'posthtml' import posthtml from 'posthtml'
import beautify from 'posthtml-beautify' import beautify from 'posthtml-beautify'
export async function formatHtmlForPrompt(html: string) { export interface FormatHtmlOptions {
html: string
keepStyles?: boolean
maxAttrLen?: number
maxContentLen?: number
}
export async function formatHtmlForPrompt({
html,
keepStyles = false,
maxAttrLen = 200,
maxContentLen = 500,
}: FormatHtmlOptions) {
const tagsToRemove = [ const tagsToRemove = [
'hint', 'hint',
'style', 'style',
@@ -11,12 +23,9 @@ export async function formatHtmlForPrompt(html: string) {
'noscript', 'noscript',
'svg', 'svg',
'head', 'head',
// 'head',
] ]
const attributesToKeep = [ const attributesToKeep = [
'data-framer-name',
// 'class',
// 'id',
'label', 'label',
'title', 'title',
'alt', 'alt',
@@ -27,12 +36,24 @@ export async function formatHtmlForPrompt(html: string) {
'placeholder', 'placeholder',
'type', 'type',
'role', 'role',
// 'src',
'target', 'target',
'data-llm-id',
'vimium-label', 'vimium-label',
// Test IDs (data-testid, data-test, data-cy are covered by data-* prefix)
'testid',
'test-id',
// Conditionally added: 'style', 'class'
] ]
if (keepStyles) {
attributesToKeep.push('style', 'class')
}
const truncate = (str: string, maxLen: number): string => {
if (str.length <= maxLen) return str
const remaining = str.length - maxLen
return str.slice(0, maxLen) + `...${remaining} more characters`
}
// Create a custom plugin to remove tags and filter attributes // Create a custom plugin to remove tags and filter attributes
const removeTagsAndAttrsPlugin = () => { const removeTagsAndAttrsPlugin = () => {
return (tree) => { return (tree) => {
@@ -48,7 +69,10 @@ export async function formatHtmlForPrompt(html: string) {
// Process each node recursively // Process each node recursively
const processNode = (node) => { const processNode = (node) => {
if (typeof node === 'string') { if (typeof node === 'string') {
return node // Truncate text content
const trimmed = node.trim()
if (trimmed.length === 0) return node
return truncate(node, maxContentLen)
} }
// Remove unwanted tags // Remove unwanted tags
@@ -60,8 +84,16 @@ export async function formatHtmlForPrompt(html: string) {
if (node.attrs) { if (node.attrs) {
const newAttrs: typeof node.attrs = {} const newAttrs: typeof node.attrs = {}
for (const [attr, value] of Object.entries(node.attrs)) { for (const [attr, value] of Object.entries(node.attrs)) {
if (attr.startsWith('aria-') || attributesToKeep.includes(attr)) { const shouldKeep =
newAttrs[attr] = value attr.startsWith('aria-') ||
attr.startsWith('data-') ||
attributesToKeep.includes(attr)
if (shouldKeep) {
// Truncate attribute values
newAttrs[attr] = typeof value === 'string'
? truncate(value, maxAttrLen)
: value
} }
} }
node.attrs = newAttrs node.attrs = newAttrs
@@ -122,18 +154,15 @@ export async function formatHtmlForPrompt(html: string) {
// Check for consecutive empty elements (skipping whitespace-only strings) // Check for consecutive empty elements (skipping whitespace-only strings)
if (isEmptyElement(current)) { if (isEmptyElement(current)) {
const emptyElements = [current] const emptyElements = [current]
const indicesToSkip = [i]
let j = i + 1 let j = i + 1
while (j < content.length) { while (j < content.length) {
if (isWhitespaceOnly(content[j])) { if (isWhitespaceOnly(content[j])) {
indicesToSkip.push(j)
j++ j++
continue continue
} }
if (isEmptyElement(content[j]) && content[j].tag === current.tag) { if (isEmptyElement(content[j]) && content[j].tag === current.tag) {
emptyElements.push(content[j]) emptyElements.push(content[j])
indicesToSkip.push(j)
j++ j++
continue continue
} }