UNPKG

chrome-devtools-frontend

Version:
195 lines (190 loc) • 7.19 kB
// Copyright 2025 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. /** * @fileoverview A library to identify and templatize manually constructed Toolbars. */ import type {TSESTree} from '@typescript-eslint/utils'; import {isIdentifier, isIdentifierChain, isMemberExpression} from './ast.ts'; import {DomFragment} from './dom-fragment.ts'; type Node = TSESTree.Node; export const toolbar = { create(context) { const sourceCode = context.getSourceCode(); return { getEvent(event: Node): string | null { switch (sourceCode.getText(event)) { case 'UI.Toolbar.ToolbarInput.Event.TEXT_CHANGED': return 'change'; case 'UI.Toolbar.ToolbarInput.Event.ENTER_PRESSED': return 'submit'; case 'UI.Toolbar.ToolbarButton.Events.CLICK': return 'click'; default: return null; } }, methodCall(property: Node, firstArg: Node, _secondArg: Node, domFragment: DomFragment, _call: Node): boolean { if (isIdentifier(property, 'appendToolbarItem')) { domFragment.appendChild(firstArg, sourceCode); return true; } return false; }, NewExpression(node) { const toolbarItem = isMemberExpression(node.callee, n => isIdentifierChain(n, ['UI', 'Toolbar']), n => n.type === 'Identifier'); if (!toolbarItem) { return; } if (isIdentifier(toolbarItem, ['ToolbarFilter', 'ToolbarInput'])) { const domFragment = DomFragment.getOrCreate(node, sourceCode); domFragment.tagName = 'devtools-toolbar-input'; const type = isIdentifier(toolbarItem, 'ToolbarFilter') ? 'filter' : 'text'; domFragment.attributes.push({ key: 'type', value: type, }); const args = [...node.arguments]; const placeholder = args.shift(); if (placeholder && !isIdentifier(placeholder, 'undefined')) { domFragment.attributes.push({ key: 'placeholder', value: placeholder, }); } if (type === 'text') { const accesiblePlaceholder = args.shift(); if (accesiblePlaceholder && !isIdentifier(accesiblePlaceholder, 'undefined')) { domFragment.attributes.push({ key: 'aria-label', value: accesiblePlaceholder, }); } } const flexGrow = args.shift(); if (flexGrow && !isIdentifier(flexGrow, 'undefined')) { domFragment.style.push({ key: 'flex-grow', value: flexGrow, }); } const flexShrink = args.shift(); if (flexShrink && !isIdentifier(flexShrink, 'undefined')) { domFragment.style.push({ key: 'flex-shrink', value: flexShrink, }); } const title = args.shift(); if (title && !isIdentifier(title, 'undefined')) { domFragment.attributes.push({ key: 'title', value: title, }); } const completions = args.shift(); if (completions && !isIdentifier(completions, 'undefined')) { domFragment.attributes.push({ key: 'list', value: 'completions', }); const dataList = domFragment.appendChild(completions, sourceCode); dataList.tagName = 'datalist'; dataList.attributes.push({ key: 'id', value: 'completions', }); dataList.textContent = completions; } args.shift(); // dynamicCompletions is not supported const jslogContext = args.shift(); if (jslogContext && !isIdentifier(jslogContext, 'undefined')) { domFragment.attributes.push({ key: 'id', value: jslogContext, }); } } if (isIdentifier(toolbarItem, 'ToolbarButton')) { const domFragment = DomFragment.getOrCreate(node, sourceCode); domFragment.tagName = 'devtools-button'; const title = node.arguments[0]; domFragment.bindings.push({ key: 'variant', value: '${Buttons.Button.Variant.TOOLBAR}', }); if (title && !isIdentifier(title, 'undefined')) { domFragment.attributes.push({ key: 'title', value: title, }); } const glyph = node.arguments[1]; if (glyph && !isIdentifier(glyph, 'undefined')) { domFragment.bindings.push({ key: 'iconName', value: glyph, }); } const text = node.arguments[2]; if (text && !isIdentifier(text, 'undefined')) { domFragment.textContent = text; } const jslogContext = node.arguments[3]; if (jslogContext && !isIdentifier(jslogContext, 'undefined')) { domFragment.bindings.push({ key: 'jslogContext', value: jslogContext, }); } } if (isIdentifier(toolbarItem, ['ToolbarCheckbox', 'ToolbarSettingCheckbox'])) { const domFragment = DomFragment.getOrCreate(node, sourceCode); domFragment.tagName = 'devtools-checkbox'; const title = node.arguments[0]; if (title && !isIdentifier(title, 'undefined')) { let text: Node|string = title; if (isIdentifier(toolbarItem, 'ToolbarSettingCheckbox')) { domFragment.directives.push({ name: 'bindToSetting', arguments: [title], }); const alternateTitle = node.arguments[2]; if (alternateTitle && !isIdentifier(alternateTitle, 'undefined')) { text = alternateTitle; } else { text = '${' + sourceCode.getText(title) + '.title()}'; } } domFragment.textContent = text; } const tooltip = node.arguments[1]; if (tooltip && !isIdentifier(tooltip, 'undefined')) { domFragment.attributes.push({ key: 'title', value: tooltip, }); } if (isIdentifier(toolbarItem, 'ToolbarCheckbox')) { const listener = node.arguments[2]; if (listener && !isIdentifier(listener, 'undefined')) { domFragment.eventListeners.push({ key: 'click', value: listener, }); } const jslogContext = node.arguments[3]; if (jslogContext && !isIdentifier(jslogContext, 'undefined')) { domFragment.bindings.push({ key: 'jslogContext', value: jslogContext, }); } } } } }; } };