mirror of
				https://github.com/microsoft/playwright.git
				synced 2025-06-26 21:40:17 +00:00 
			
		
		
		
	chore: add simple dom util (#32332)
This commit is contained in:
		
							parent
							
								
									6f55b57e5a
								
							
						
					
					
						commit
						177576a51b
					
				
							
								
								
									
										82
									
								
								packages/playwright-core/src/server/injected/simpleDom.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								packages/playwright-core/src/server/injected/simpleDom.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,82 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) Microsoft Corporation.
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import { escapeHTMLAttribute, escapeHTML } from '@isomorphic/stringUtils';
 | 
			
		||||
import { beginAriaCaches, endAriaCaches, getAriaRole, getElementAccessibleName } from './roleUtils';
 | 
			
		||||
import { isElementVisible } from './domUtils';
 | 
			
		||||
 | 
			
		||||
const leafRoles = new Set([
 | 
			
		||||
  'button',
 | 
			
		||||
  'checkbox',
 | 
			
		||||
  'combobox',
 | 
			
		||||
  'link',
 | 
			
		||||
  'textbox',
 | 
			
		||||
]);
 | 
			
		||||
 | 
			
		||||
export function simpleDom(document: Document): { markup: string, elements: Map<string, Element> } {
 | 
			
		||||
  const normalizeWhitespace = (text: string) => text.replace(/[\s\n]+/g, match => match.includes('\n') ? '\n' : ' ');
 | 
			
		||||
  const tokens: string[] = [];
 | 
			
		||||
  const idMap = new Map<string, Element>();
 | 
			
		||||
  let lastId = 0;
 | 
			
		||||
  const visit = (node: Node) => {
 | 
			
		||||
    if (node.nodeType === Node.TEXT_NODE) {
 | 
			
		||||
      tokens.push(node.nodeValue!);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (node.nodeType === Node.ELEMENT_NODE) {
 | 
			
		||||
      const element = node as Element;
 | 
			
		||||
      if (element.nodeName === 'SCRIPT' || element.nodeName === 'STYLE' || element.nodeName === 'NOSCRIPT')
 | 
			
		||||
        return;
 | 
			
		||||
      if (isElementVisible(element)) {
 | 
			
		||||
        const role = getAriaRole(element) as string;
 | 
			
		||||
        if (role && leafRoles.has(role)) {
 | 
			
		||||
          let value: string | undefined;
 | 
			
		||||
          if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA')
 | 
			
		||||
            value = (element as HTMLInputElement | HTMLTextAreaElement).value;
 | 
			
		||||
          const name = getElementAccessibleName(element, false);
 | 
			
		||||
          const structuralId = String(++lastId);
 | 
			
		||||
          idMap.set(structuralId, element);
 | 
			
		||||
          tokens.push(renderTag(role, name, structuralId, { value }));
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      for (let child = element.firstChild; child; child = child.nextSibling)
 | 
			
		||||
        visit(child);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
  beginAriaCaches();
 | 
			
		||||
  try {
 | 
			
		||||
    visit(document.body);
 | 
			
		||||
  } finally {
 | 
			
		||||
    endAriaCaches();
 | 
			
		||||
  }
 | 
			
		||||
  return {
 | 
			
		||||
    markup: normalizeWhitespace(tokens.join(' ')),
 | 
			
		||||
    elements: idMap
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function renderTag(role: string, name: string, id: string, params?: { value?: string }): string {
 | 
			
		||||
  const escapedTextContent = escapeHTML(name);
 | 
			
		||||
  const escapedValue = escapeHTMLAttribute(params?.value || '');
 | 
			
		||||
  switch (role) {
 | 
			
		||||
    case 'button': return `<button id="${id}">${escapedTextContent}</button>`;
 | 
			
		||||
    case 'link': return `<a id="${id}">${escapedTextContent}</a>`;
 | 
			
		||||
    case 'textbox': return `<input id="${id}" title="${escapedTextContent}" value="${escapedValue}"></input>`;
 | 
			
		||||
  }
 | 
			
		||||
  return `<div role=${role} id="${id}">${escapedTextContent}</div>`;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user