99 */
1010'use strict' ;
1111
12- const { isIdentifier, isMemberExpression, getEnclosingExpression} = require ( './no-imperative-dom-api/ast.js' ) ;
12+ const adorner = require ( './no-imperative-dom-api/adorner.js' ) ;
13+ const { isIdentifier, getEnclosingExpression} = require ( './no-imperative-dom-api/ast.js' ) ;
14+ const domApiDevtoolsExtensions = require ( './no-imperative-dom-api/dom-api-devtools-extensions.js' ) ;
15+ const domApi = require ( './no-imperative-dom-api/dom-api.js' ) ;
1316const { DomFragment} = require ( './no-imperative-dom-api/dom-fragment.js' ) ;
17+ const toolbar = require ( './no-imperative-dom-api/toolbar.js' ) ;
18+ const widget = require ( './no-imperative-dom-api/widget.js' ) ;
1419
1520/** @typedef {import('eslint').Rule.Node } Node */
1621/** @typedef {import('eslint').AST.SourceLocation } SourceLocation */
@@ -33,22 +38,29 @@ module.exports = {
3338 create : function ( context ) {
3439 const sourceCode = context . getSourceCode ( ) ;
3540
41+ const subrules = [
42+ adorner . create ( context ) ,
43+ domApi . create ( context ) ,
44+ domApiDevtoolsExtensions . create ( context ) ,
45+ toolbar . create ( context ) ,
46+ widget . create ( context ) ,
47+ ] ;
48+
3649 /**
3750 * @param {Node } event
3851 * @return {string|null }
3952 */
4053 function getEvent ( event ) {
41- switch ( sourceCode . getText ( event ) ) {
42- case 'UI.Toolbar.ToolbarInput.Event.TEXT_CHANGED' :
43- return 'change' ;
44- case 'UI.Toolbar.ToolbarInput.Event.ENTER_PRESSED' :
45- return 'submit' ;
46- default :
47- if ( event . type === 'Literal' ) {
48- return event . value . toString ( ) ;
49- }
50- return null ;
54+ for ( const rule of subrules ) {
55+ const result = rule . getEvent ?. ( event ) ;
56+ if ( result ) {
57+ return result ;
58+ }
59+ }
60+ if ( event . type === 'Literal' ) {
61+ return event . value . toString ( ) ;
5162 }
63+ return null ;
5264 }
5365
5466 /**
@@ -77,76 +89,24 @@ module.exports = {
7789 const subproperty =
7890 isSubpropertyAssignment && grandParent . property . type === 'Identifier' ? grandParent . property : null ;
7991 const subpropertyValue = isSubpropertyAssignment ? /** @type {Node } */ ( grandGrandParent . right ) : null ;
80- if ( isPropertyAssignment && isIdentifier ( property , 'className' ) ) {
81- domFragment . classList . push ( propertyValue ) ;
82- } else if ( isPropertyAssignment && isIdentifier ( property , [ 'textContent' , 'innerHTML' ] ) ) {
83- domFragment . textContent = propertyValue ;
84- } else if (
85- isPropertyAssignment && domFragment . tagName === 'devtools-adorner' && isIdentifier ( property , 'data' ) &&
86- propertyValue . type === 'ObjectExpression' ) {
87- for ( const property of propertyValue . properties ) {
88- if ( property . type !== 'Property' ) {
89- continue ;
90- }
91- const key = /** @type {Node } */ ( property . key ) ;
92- if ( isIdentifier ( key , 'name' ) ) {
93- domFragment . attributes . push ( {
94- key : 'aria-label' ,
95- value : /** @type {Node } */ ( property . value ) ,
96- } ) ;
97- }
98- if ( isIdentifier ( key , 'jslogContext' ) ) {
99- domFragment . attributes . push (
100- { key : 'jslog' , value : '${VisualLogging.adorner(' + sourceCode . getText ( property . value ) + ')}' } ) ;
101- }
102- if ( isIdentifier ( key , 'content' ) ) {
103- const childFragment = DomFragment . getOrCreate ( /** @type {Node } */ ( property . value ) , sourceCode ) ;
104- childFragment . parent = domFragment ;
105- domFragment . children . push ( childFragment ) ;
106- }
107- }
108- } else if ( isMethodCall && isIdentifier ( property , 'setAttribute' ) ) {
109- const attribute = firstArg ;
110- const value = secondArg ;
111- if ( attribute . type === 'Literal' && value . type !== 'SpreadElement' ) {
112- domFragment . attributes . push ( { key : attribute . value . toString ( ) , value} ) ;
113- }
114- } else if ( isMethodCall && isIdentifier ( property , 'addEventListener' ) ) {
115- const event = getEvent ( firstArg ) ;
116- const value = secondArg ;
117- if ( event && value . type !== 'SpreadElement' ) {
118- domFragment . eventListeners . push ( { key : event , value} ) ;
119- }
120- } else if ( isMethodCall && isIdentifier ( property , 'appendToolbarItem' ) ) {
121- const childFragment = DomFragment . getOrCreate ( firstArg , sourceCode ) ;
122- childFragment . parent = domFragment ;
123- domFragment . children . push ( childFragment ) ;
124- } else if (
125- isPropertyMethodCall && isIdentifier ( property , 'classList' ) &&
126- isIdentifier ( /** @type {Node } */ ( grandParent . property ) , 'add' ) ) {
127- domFragment . classList . push ( propertyMethodArgument ) ;
128- } else if ( isSubpropertyAssignment && isIdentifier ( property , 'style' ) ) {
129- const property = subproperty . name . replace ( / ( [ a - z ] ) ( [ A - Z ] ) / g, '$1-$2' ) . toLowerCase ( ) ;
130- if ( subpropertyValue . type !== 'SpreadElement' ) {
131- domFragment . style . push ( {
132- key : property ,
133- value : subpropertyValue ,
134- } ) ;
135- }
136- } else if ( isMethodCall && isIdentifier ( property , 'createChild' ) ) {
137- if ( firstArg ?. type === 'Literal' ) {
138- const childFragment = DomFragment . getOrCreate ( grandParent , sourceCode ) ;
139- childFragment . tagName = String ( firstArg . value ) ;
140- childFragment . parent = domFragment ;
141- domFragment . children . push ( childFragment ) ;
142- if ( secondArg ) {
143- childFragment . classList . push ( secondArg ) ;
92+ for ( const rule of subrules ) {
93+ if ( isPropertyAssignment ) {
94+ rule . propertyAssignment ?. ( property , propertyValue , domFragment ) ;
95+ } else if ( isMethodCall ) {
96+ if ( isIdentifier ( property , 'addEventListener' ) ) {
97+ const event = getEvent ( firstArg ) ;
98+ const value = secondArg ;
99+ if ( event && value . type !== 'SpreadElement' ) {
100+ domFragment . eventListeners . push ( { key : event , value} ) ;
101+ }
102+ return ;
144103 }
104+ rule . methodCall ?. ( property , firstArg , secondArg , domFragment , grandParent ) ;
105+ } else if ( isPropertyMethodCall ) {
106+ rule . propertyMethodCall ?. ( property , grandParent . property , propertyMethodArgument , domFragment ) ;
107+ } else if ( isSubpropertyAssignment ) {
108+ rule . subpropertyAssignment ?. ( property , subproperty , subpropertyValue , domFragment ) ;
145109 }
146- } else if ( isMethodCall && isIdentifier ( property , 'appendChild' ) ) {
147- const childFragment = DomFragment . getOrCreate ( firstArg , sourceCode ) ;
148- childFragment . parent = domFragment ;
149- domFragment . children . push ( childFragment ) ;
150110 }
151111 }
152112
@@ -214,133 +174,18 @@ export const DEFAULT_VIEW = (input, _output, target) => {
214174 return {
215175 MemberExpression ( node ) {
216176 if ( node . object . type === 'ThisExpression' ) {
217- const domFragment = DomFragment . getOrCreate ( node , sourceCode ) ;
218- if ( isIdentifier ( node . property , 'contentElement' ) ) {
219- domFragment . tagName = 'div' ;
220- }
177+ DomFragment . getOrCreate ( node , sourceCode ) ;
221178 }
222- if ( isIdentifier ( node . object , 'document' ) && isIdentifier ( node . property , 'createElement' )
223- && node . parent . type === 'CallExpression' && node . parent . callee === node ) {
224- const domFragment = DomFragment . getOrCreate ( node . parent , sourceCode ) ;
225- if ( node . parent . arguments . length >= 1 && node . parent . arguments [ 0 ] . type === 'Literal' ) {
226- domFragment . tagName = node . parent . arguments [ 0 ] . value ;
179+ for ( const rule of subrules ) {
180+ if ( 'MemberExpression' in rule ) {
181+ rule . MemberExpression ( node ) ;
227182 }
228183 }
229184 } ,
230185 NewExpression ( node ) {
231- if ( isMemberExpression (
232- node . callee , n => isMemberExpression ( n , n => isIdentifier ( n , 'UI' ) , n => isIdentifier ( n , 'Toolbar' ) ) ,
233- n => isIdentifier ( n , [ 'ToolbarFilter' , 'ToolbarInput' ] ) ) ) {
234- const domFragment = DomFragment . getOrCreate ( node , sourceCode ) ;
235- domFragment . tagName = 'devtools-toolbar-input' ;
236- const type = isIdentifier ( node . callee . property , 'ToolbarFilter' ) ? 'filter' : 'text' ;
237- domFragment . attributes . push ( {
238- key : 'type' ,
239- value : type ,
240- } ) ;
241- const args = [ ...node . arguments ] ;
242- const placeholder = args . shift ( ) ;
243- if ( placeholder && ! isIdentifier ( placeholder , 'undefined' ) ) {
244- domFragment . attributes . push ( {
245- key : 'placeholder' ,
246- value : placeholder ,
247- } ) ;
248- }
249- if ( type === 'text' ) {
250- const accesiblePlaceholder = args . shift ( ) ;
251- if ( accesiblePlaceholder && ! isIdentifier ( accesiblePlaceholder , 'undefined' ) ) {
252- domFragment . attributes . push ( {
253- key : 'aria-label' ,
254- value : accesiblePlaceholder ,
255- } ) ;
256- }
257- }
258- const flexGrow = args . shift ( ) ;
259- if ( flexGrow && ! isIdentifier ( flexGrow , 'undefined' ) ) {
260- domFragment . style . push ( {
261- key : 'flex-grow' ,
262- value : flexGrow ,
263- } ) ;
264- }
265- const flexShrink = args . shift ( ) ;
266- if ( flexShrink && ! isIdentifier ( flexShrink , 'undefined' ) ) {
267- domFragment . style . push ( {
268- key : 'flex-shrink' ,
269- value : flexShrink ,
270- } ) ;
271- }
272- const title = args . shift ( ) ;
273- if ( title && ! isIdentifier ( title , 'undefined' ) ) {
274- domFragment . attributes . push ( {
275- key : 'title' ,
276- value : title ,
277- } ) ;
278- }
279- const completions = args . shift ( ) ;
280- if ( completions && ! isIdentifier ( completions , 'undefined' ) ) {
281- domFragment . attributes . push ( {
282- key : 'list' ,
283- value : 'completions' ,
284- } ) ;
285- const dataList = DomFragment . getOrCreate ( completions , sourceCode ) ;
286- dataList . tagName = 'datalist' ;
287- dataList . attributes . push ( {
288- key : 'id' ,
289- value : 'completions' ,
290- } ) ;
291- dataList . textContent = completions ;
292- domFragment . children . push ( dataList ) ;
293- dataList . parent = domFragment ;
294- }
295- args . shift ( ) ; // dynamicCompletions is not supported
296- const jslogContext = args . shift ( ) ;
297- if ( jslogContext && ! isIdentifier ( jslogContext , 'undefined' ) ) {
298- domFragment . attributes . push ( {
299- key : 'id' ,
300- value : jslogContext ,
301- } ) ;
302- }
303- }
304- if ( isMemberExpression (
305- node . callee ,
306- n => isMemberExpression ( n , n => isIdentifier ( n , 'Adorners' ) , n => isIdentifier ( n , 'Adorner' ) ) ,
307- n => isIdentifier ( n , 'Adorner' ) ) ) {
308- const domFragment = DomFragment . getOrCreate ( node , sourceCode ) ;
309- domFragment . tagName = 'devtools-adorner' ;
310- }
311- if ( isMemberExpression (
312- node . callee , n => isMemberExpression ( n , n => isIdentifier ( n , 'UI' ) , n => isIdentifier ( n , 'Toolbar' ) ) ,
313- n => isIdentifier ( n , 'ToolbarButton' ) ) ) {
314- const domFragment = DomFragment . getOrCreate ( node , sourceCode ) ;
315- domFragment . tagName = 'devtools-button' ;
316- const title = node . arguments [ 0 ] ;
317- domFragment . bindings . push ( {
318- key : 'variant' ,
319- value : '${Buttons.Button.Variant.TOOLBAR}' ,
320- } ) ;
321- if ( title && ! isIdentifier ( title , 'undefined' ) ) {
322- domFragment . attributes . push ( {
323- key : 'title' ,
324- value : title ,
325- } ) ;
326- }
327- const glyph = node . arguments [ 1 ] ;
328- if ( glyph && ! isIdentifier ( glyph , 'undefined' ) ) {
329- domFragment . bindings . push ( {
330- key : 'iconName' ,
331- value : glyph ,
332- } ) ;
333- }
334- const text = node . arguments [ 2 ] ;
335- if ( text && ! isIdentifier ( text , 'undefined' ) ) {
336- domFragment . textContent = text ;
337- }
338- const jslogContext = node . arguments [ 3 ] ;
339- if ( jslogContext && ! isIdentifier ( jslogContext , 'undefined' ) ) {
340- domFragment . bindings . push ( {
341- key : 'jslogContext' ,
342- value : jslogContext ,
343- } ) ;
186+ for ( const rule of subrules ) {
187+ if ( 'NewExpression' in rule ) {
188+ rule . NewExpression ( node ) ;
344189 }
345190 }
346191 } ,
0 commit comments