claude-playwright
Version:
Seamless integration between Claude Code and Playwright MCP for efficient browser automation and testing
1 lines • 17.1 kB
Source Map (JSON)
{"version":3,"sources":["../../src/core/smart-normalizer.ts"],"sourcesContent":["import crypto from 'crypto';\n\ninterface PositionalKeyword {\n word: string;\n position: number;\n context?: string;\n}\n\ninterface InputFeatures {\n hasId: boolean;\n hasClass: boolean;\n hasQuoted: boolean;\n numbers: string[];\n positions: PositionalKeyword[];\n attributes: string[];\n wordCount: number;\n hasImperative: boolean;\n casePattern: 'lower' | 'upper' | 'mixed' | 'title';\n isNavigation: boolean;\n isFormAction: boolean;\n hasDataTestId: boolean;\n}\n\nexport interface NormalizationResult {\n normalized: string;\n tokens: string[];\n positions: PositionalKeyword[];\n features: InputFeatures;\n hash: string;\n}\n\nexport class SmartNormalizer {\n private readonly POSITION_KEYWORDS = [\n 'before', 'after', 'first', 'last', 'next', 'previous', \n 'above', 'below', 'top', 'bottom', 'left', 'right'\n ];\n \n private readonly RELATION_KEYWORDS = [\n 'in', 'of', 'from', 'to', 'with', 'by', 'for'\n ];\n \n private readonly STOP_WORDS = [\n 'the', 'a', 'an', 'and', 'or', 'but', 'at', 'on'\n ];\n \n private readonly ACTION_SYNONYMS = {\n 'click': ['click', 'press', 'tap', 'hit', 'select', 'choose'],\n 'type': ['type', 'enter', 'input', 'fill', 'write'],\n 'navigate': ['go', 'navigate', 'open', 'visit', 'load'],\n 'hover': ['hover', 'mouseover', 'move']\n };\n\n normalize(input: string): NormalizationResult {\n const original = input.trim();\n const features = this.extractFeatures(original);\n \n // Step 1: Basic cleanup\n let text = original.toLowerCase();\n \n // Step 2: Extract and preserve quoted strings\n const quotedStrings: string[] = [];\n text = text.replace(/([\"'])((?:(?!\\1)[^\\\\]|\\\\.)*)(\\1)/g, (match, quote, content) => {\n quotedStrings.push(content);\n return `QUOTED_${quotedStrings.length - 1}`;\n });\n \n // Step 3: Extract positional information\n const positions = this.extractPositions(text);\n \n // Step 4: Normalize actions to canonical forms\n text = this.normalizeActions(text);\n \n // Step 5: Remove common patterns\n text = this.removeCommonPatterns(text);\n \n // Step 6: Tokenize and filter\n const words = text.split(/\\s+/).filter(word => word.length > 0);\n const tokens = [];\n const preserved = [];\n \n for (let i = 0; i < words.length; i++) {\n const word = words[i];\n \n if (this.POSITION_KEYWORDS.includes(word)) {\n // Preserve positional keywords with context\n preserved.push({\n word,\n position: i,\n context: words[i + 1] || null\n });\n } else if (!this.STOP_WORDS.includes(word) && \n !this.RELATION_KEYWORDS.includes(word) &&\n !['button', 'field', 'element'].includes(word)) {\n tokens.push(word);\n }\n }\n \n // Step 7: Sort tokens for order-invariance (except preserved)\n tokens.sort();\n \n // Step 8: Build normalized string\n let normalized = tokens.join(' ');\n \n // Step 9: Add positional information\n if (preserved.length > 0) {\n const posInfo = preserved.map(p => \n `${p.word}${p.context ? '-' + p.context : ''}`\n ).join(',');\n normalized += ` _pos:${posInfo}`;\n }\n \n // Step 10: Add quoted content back\n if (quotedStrings.length > 0) {\n normalized += ` _quoted:${quotedStrings.join(',')}`;\n }\n \n const hash = crypto.createHash('md5').update(normalized).digest('hex');\n \n return {\n normalized,\n tokens,\n positions,\n features,\n hash\n };\n }\n\n extractFeatures(input: string): InputFeatures {\n const text = input.toLowerCase();\n \n return {\n hasId: /#[\\w-]+/.test(input),\n hasClass: /\\.[\\w-]+/.test(input),\n hasQuoted: /\"[^\"]+\"|'[^']+'/.test(input),\n numbers: (input.match(/\\d+/g) || []),\n positions: this.extractPositions(text),\n attributes: this.extractAttributes(input),\n wordCount: input.split(/\\s+/).length,\n hasImperative: /^(click|press|tap|select|enter|type|fill)/i.test(input),\n casePattern: this.detectCasePattern(input),\n isNavigation: /^(go|navigate|open|visit)/i.test(input),\n isFormAction: /(submit|enter|fill|type|input)/i.test(input),\n hasDataTestId: /data-test|testid|data-cy/i.test(input)\n };\n }\n\n private extractPositions(text: string): PositionalKeyword[] {\n const positions: PositionalKeyword[] = [];\n const words = text.split(/\\s+/);\n \n for (let i = 0; i < words.length; i++) {\n const word = words[i];\n if (this.POSITION_KEYWORDS.includes(word)) {\n positions.push({\n word,\n position: i,\n context: words[i + 1] || words[i - 1] || undefined\n });\n }\n }\n \n return positions;\n }\n\n private extractAttributes(input: string): string[] {\n const attributes = [];\n \n // Extract common attribute patterns\n const patterns = [\n /\\[([^\\]]+)\\]/g, // [attribute=value]\n /data-[\\w-]+/g, // data-testid\n /aria-[\\w-]+/g, // aria-label\n /role=\"[\\w-]+\"/g, // role=\"button\"\n /type=\"[\\w-]+\"/g, // type=\"submit\"\n /placeholder=\"[^\"]+\"/g // placeholder=\"text\"\n ];\n \n for (const pattern of patterns) {\n const matches = input.match(pattern);\n if (matches) {\n attributes.push(...matches);\n }\n }\n \n return attributes;\n }\n\n private detectCasePattern(input: string): 'lower' | 'upper' | 'mixed' | 'title' {\n const hasLower = /[a-z]/.test(input);\n const hasUpper = /[A-Z]/.test(input);\n \n if (!hasLower && hasUpper) return 'upper';\n if (hasLower && !hasUpper) return 'lower';\n \n // Check if it's title case\n const words = input.split(/\\s+/);\n const isTitleCase = words.every(word => \n /^[A-Z][a-z]*$/.test(word) || /^[a-z]+$/.test(word)\n );\n \n return isTitleCase ? 'title' : 'mixed';\n }\n\n private normalizeActions(text: string): string {\n for (const [canonical, synonyms] of Object.entries(this.ACTION_SYNONYMS)) {\n for (const synonym of synonyms) {\n const regex = new RegExp(`\\\\b${synonym}\\\\b`, 'g');\n text = text.replace(regex, canonical);\n }\n }\n return text;\n }\n\n private removeCommonPatterns(text: string): string {\n // Remove common prefixes and suffixes\n text = text.replace(/^(click|press|tap)(\\s+on)?(\\s+the)?/i, 'click');\n text = text.replace(/\\s+(button|element|field)$/i, '');\n text = text.replace(/button\\s+/i, '');\n \n // Remove articles and common words\n text = text.replace(/\\b(the|a|an)\\b/g, '');\n \n // Clean up punctuation\n text = text.replace(/[^\\w\\s#._-]/g, ' ');\n \n // Normalize whitespace\n text = text.replace(/\\s+/g, ' ').trim();\n \n return text;\n }\n\n // Utility methods for similarity\n calculateSimilarity(result1: NormalizationResult, result2: NormalizationResult): number {\n // Token-based Jaccard similarity\n const set1 = new Set(result1.tokens);\n const set2 = new Set(result2.tokens);\n const intersection = new Set([...set1].filter(x => set2.has(x)));\n const union = new Set([...set1, ...set2]);\n \n let similarity = intersection.size / union.size;\n \n // Boost for matching quoted strings\n const quoted1 = result1.normalized.match(/_quoted:([^_]*)/)?.[1] || '';\n const quoted2 = result2.normalized.match(/_quoted:([^_]*)/)?.[1] || '';\n if (quoted1 === quoted2 && quoted1.length > 0) {\n similarity += 0.2;\n }\n \n // Penalty for mismatched positions\n const pos1 = result1.normalized.match(/_pos:([^_]*)/)?.[1] || '';\n const pos2 = result2.normalized.match(/_pos:([^_]*)/)?.[1] || '';\n if (pos1 !== pos2 && (pos1.length > 0 || pos2.length > 0)) {\n similarity -= 0.3;\n }\n \n return Math.max(0, Math.min(1, similarity));\n }\n\n // Fuzzy matching for typo tolerance\n damerauLevenshtein(a: string, b: string): number {\n const da: { [key: string]: number } = {};\n const maxdist = a.length + b.length;\n const H: number[][] = [];\n \n H[-1] = [];\n H[-1][-1] = maxdist;\n \n for (let i = 0; i <= a.length; i++) {\n H[i] = [];\n H[i][-1] = maxdist;\n H[i][0] = i;\n }\n \n for (let j = 0; j <= b.length; j++) {\n H[-1][j] = maxdist;\n H[0][j] = j;\n }\n \n for (let i = 1; i <= a.length; i++) {\n let db = 0;\n for (let j = 1; j <= b.length; j++) {\n const k = da[b[j - 1]] || 0;\n const l = db;\n let cost = 1;\n if (a[i - 1] === b[j - 1]) {\n cost = 0;\n db = j;\n }\n \n H[i][j] = Math.min(\n H[i - 1][j] + 1, // insertion\n H[i][j - 1] + 1, // deletion\n H[i - 1][j - 1] + cost, // substitution\n H[k - 1][l - 1] + (i - k - 1) + 1 + (j - l - 1) // transposition\n );\n }\n da[a[i - 1]] = i;\n }\n \n return H[a.length][b.length];\n }\n\n // Create fuzzy variations for learning\n generateVariations(input: string): string[] {\n const variations = [input];\n const normalized = this.normalize(input);\n \n // Generate common variations\n variations.push(input.toLowerCase());\n variations.push(input.replace(/\\s+/g, ' ').trim());\n variations.push(input.replace(/^(click|press)\\s+/i, 'tap '));\n variations.push(input.replace(/\\s+button$/i, ''));\n \n // Token permutations (limited)\n if (normalized.tokens.length <= 4) {\n const permutations = this.generateTokenPermutations(normalized.tokens);\n variations.push(...permutations.slice(0, 3)); // Limit to 3 permutations\n }\n \n return [...new Set(variations)];\n }\n\n private generateTokenPermutations(tokens: string[]): string[] {\n if (tokens.length <= 1) return tokens;\n if (tokens.length > 4) return []; // Too many combinations\n \n const result: string[] = [];\n const permute = (arr: string[], start = 0) => {\n if (start === arr.length) {\n result.push(arr.join(' '));\n return;\n }\n \n for (let i = start; i < arr.length; i++) {\n [arr[start], arr[i]] = [arr[i], arr[start]];\n permute(arr, start + 1);\n [arr[start], arr[i]] = [arr[i], arr[start]]; // backtrack\n }\n };\n \n permute([...tokens]);\n return result;\n }\n}"],"mappings":"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","names":["crypto"]}