glass-easel-devtools-agent 0.9.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -126,7 +126,7 @@ export class MountPointsManager {
126
126
  virtual: false,
127
127
  is: '',
128
128
  id: '',
129
- class: '',
129
+ classes: [],
130
130
  slot: '',
131
131
  slotName: undefined,
132
132
  slotValues: undefined,
@@ -152,7 +152,8 @@ export class MountPointsManager {
152
152
  if (nativeNode) is = nativeNode.is
153
153
  if (virtualNode) is = virtualNode.is
154
154
  const id = elem.id
155
- const nodeClass = elem.class
155
+ const classEdit = backendUtils.classEditContext.createOrGet('', elem)
156
+ const classes = classEdit.update(elem.class.split(/\s+/g).filter((x) => x)).getClasses()
156
157
  const slot = elem.slot
157
158
  let slotName
158
159
  const maybeSlotName = Reflect.get(elem, '_$slotName') as unknown
@@ -206,7 +207,9 @@ export class MountPointsManager {
206
207
  // collect attributes, properties, and external classes
207
208
  let normalAttributes: { name: string; value: GlassEaselVar }[] | undefined
208
209
  let properties: { name: string; value: GlassEaselVar }[] | undefined
209
- let externalClasses: { name: string; value: string }[] | undefined
210
+ let externalClasses:
211
+ | { name: string; value: { className: string; disabled?: boolean }[] }[]
212
+ | undefined
210
213
  if (nativeNode) {
211
214
  normalAttributes = []
212
215
  elem.attributes.forEach(({ name, value }) => {
@@ -224,7 +227,10 @@ export class MountPointsManager {
224
227
  if (ec) {
225
228
  externalClasses = Object.entries(ec).map(([name, value]) => ({
226
229
  name,
227
- value: value?.join(' ') ?? '',
230
+ value: backendUtils.classEditContext
231
+ .createOrGet(name, elem)
232
+ .update(value ?? [])
233
+ .getClasses(),
228
234
  }))
229
235
  }
230
236
  }
@@ -245,7 +251,7 @@ export class MountPointsManager {
245
251
  virtual,
246
252
  is,
247
253
  id,
248
- class: nodeClass,
254
+ classes,
249
255
  slot,
250
256
  slotName,
251
257
  slotValues,
@@ -258,6 +264,67 @@ export class MountPointsManager {
258
264
  }
259
265
  })
260
266
 
267
+ this.conn.setRequestHandler(
268
+ 'DOM.setAttributeValue',
269
+ async ({ nodeId, name, value, nameType }) => {
270
+ const { node } = this.queryActiveNode(nodeId)
271
+ const elem = node.asElement()
272
+ if (!elem) return undefined
273
+ if (nameType === 'normal-attribute') {
274
+ elem.setAttribute(name, value)
275
+ } else if (nameType === 'property') {
276
+ const comp = elem.asGeneralComponent()
277
+ comp?.setData({ [name]: value })
278
+ } else if (nameType === 'external-class') {
279
+ const comp = elem.asGeneralComponent()
280
+ comp?.setExternalClass(name, value)
281
+ } else if (name === 'id') {
282
+ elem.id = value
283
+ } else if (name === 'class') {
284
+ elem.class = value
285
+ } else if (name === 'slot') {
286
+ elem.slot = value
287
+ } else if (name.indexOf(':') >= 0) {
288
+ const [scope, key] = name.split(':', 2)
289
+ if (scope === 'dataset') {
290
+ elem.setDataset(key, value)
291
+ } else if (scope === 'mark') {
292
+ elem.setMark(key, value)
293
+ }
294
+ } else {
295
+ const comp = elem.asGeneralComponent()
296
+ if (comp) {
297
+ const beh = comp.getComponentDefinition().behavior
298
+ if (beh.listProperties().includes(name)) {
299
+ comp.setData({ [name]: value })
300
+ } else if (Object.keys(comp.getExternalClasses()).includes(name)) {
301
+ comp.setExternalClass(name, value)
302
+ }
303
+ }
304
+ elem.setAttribute(name, value)
305
+ }
306
+ return undefined
307
+ },
308
+ )
309
+
310
+ this.conn.setRequestHandler(
311
+ 'DOM.setGlassEaselClassList',
312
+ async ({ nodeId, externalClass, classes }) => {
313
+ const { node } = this.queryActiveNode(nodeId)
314
+ const elem = node.asElement()
315
+ if (!elem) return { classes: [] }
316
+ const edit = backendUtils.classEditContext.createOrGet(externalClass ?? '', elem)
317
+ edit.setClasses(classes)
318
+ if (externalClass) {
319
+ const comp = elem.asGeneralComponent()
320
+ comp?.setExternalClass(externalClass, edit.stringify())
321
+ } else {
322
+ elem.class = edit.stringify()
323
+ }
324
+ return { classes: edit.getClasses() }
325
+ },
326
+ )
327
+
261
328
  this.conn.setRequestHandler('DOM.getGlassEaselComposedChildren', async ({ nodeId }) => {
262
329
  const { node } = this.queryActiveNode(nodeId)
263
330
  const elem = node.asElement()
@@ -354,13 +421,11 @@ export class MountPointsManager {
354
421
 
355
422
  this.conn.setRequestHandler('CSS.getMatchedStylesForNode', async ({ nodeId }) => {
356
423
  const { node } = this.queryActiveNode(nodeId)
357
- const ctx = node?.getBackendContext()
358
- const elem = node?.getBackendElement()
359
- if (!ctx || !elem) {
360
- throw new Error('no such backend node found')
424
+ const elem = node.asElement()
425
+ if (!elem) {
426
+ throw new Error('not an element')
361
427
  }
362
428
  const { inline, inlineText, rules, crossOriginFailing } = await backendUtils.getMatchedRules(
363
- ctx,
364
429
  elem,
365
430
  )
366
431
  const inlineStyle = { cssProperties: inline, cssText: inlineText }
@@ -370,11 +435,77 @@ export class MountPointsManager {
370
435
  style: { cssProperties: rule.properties, cssText: rule.propertyText },
371
436
  media: rule.mediaQueries.map((x) => ({ text: x })),
372
437
  inactive: rule.inactive || false,
438
+ styleSheetId: rule.sheetIndex.toString(),
439
+ ruleIndex: rule.ruleIndex,
440
+ styleScope: rule.styleScope,
373
441
  },
374
442
  }))
375
443
  return { inlineStyle, matchedCSSRules, inherited: [], crossOriginFailing }
376
444
  })
377
445
 
446
+ this.conn.setRequestHandler(
447
+ 'CSS.replaceGlassEaselStyleSheetProperty',
448
+ async ({ nodeId, styleSheetId, ruleIndex, propertyIndex, styleText }) => {
449
+ const { node } = this.queryActiveNode(nodeId)
450
+ const ctx = node?.getBackendContext()
451
+ const elem = node?.getBackendElement()
452
+ if (!ctx || !elem) {
453
+ throw new Error('no such backend node found')
454
+ }
455
+ const editFunc = (edit: backendUtils.StyleRuleEdit) => {
456
+ edit.replace(propertyIndex, styleText)
457
+ }
458
+ if (styleSheetId !== undefined) {
459
+ const sheetIndex = Number(styleSheetId)
460
+ await backendUtils.styleEditContext.updateRule(ctx, sheetIndex, ruleIndex, editFunc)
461
+ } else {
462
+ backendUtils.styleEditContext.updateInline(ctx, elem, editFunc)
463
+ }
464
+ },
465
+ )
466
+
467
+ this.conn.setRequestHandler(
468
+ 'CSS.addGlassEaselStyleSheetProperty',
469
+ async ({ nodeId, styleSheetId, ruleIndex, styleText }) => {
470
+ const { node } = this.queryActiveNode(nodeId)
471
+ const ctx = node?.getBackendContext()
472
+ const elem = node?.getBackendElement()
473
+ if (!ctx || !elem) {
474
+ throw new Error('no such backend node found')
475
+ }
476
+ const editFunc = (edit: backendUtils.StyleRuleEdit) => {
477
+ edit.append(styleText)
478
+ }
479
+ if (styleSheetId !== undefined) {
480
+ const sheetIndex = Number(styleSheetId)
481
+ await backendUtils.styleEditContext.updateRule(ctx, sheetIndex, ruleIndex, editFunc)
482
+ } else {
483
+ backendUtils.styleEditContext.updateInline(ctx, elem, editFunc)
484
+ }
485
+ },
486
+ )
487
+
488
+ this.conn.setRequestHandler(
489
+ 'CSS.setGlassEaselStyleSheetPropertyDisabled',
490
+ async ({ nodeId, styleSheetId, ruleIndex, propertyIndex, disabled }) => {
491
+ const { node } = this.queryActiveNode(nodeId)
492
+ const ctx = node?.getBackendContext()
493
+ const elem = node?.getBackendElement()
494
+ if (!ctx || !elem) {
495
+ throw new Error('no such backend node found')
496
+ }
497
+ const editFunc = (edit: backendUtils.StyleRuleEdit) => {
498
+ edit.setDisabled(propertyIndex, disabled)
499
+ }
500
+ if (styleSheetId !== undefined) {
501
+ const sheetIndex = Number(styleSheetId)
502
+ await backendUtils.styleEditContext.updateRule(ctx, sheetIndex, ruleIndex, editFunc)
503
+ } else {
504
+ backendUtils.styleEditContext.updateInline(ctx, elem, editFunc)
505
+ }
506
+ },
507
+ )
508
+
378
509
  this.conn.setRequestHandler('Overlay.setInspectMode', async ({ mode }) => {
379
510
  if (mode === 'searchForNode') {
380
511
  let prevHighlight = 0
@@ -575,8 +706,12 @@ export class MountPointsManager {
575
706
  const marks = Reflect.get(elem, '_$marks') as { [key: string]: unknown } | undefined
576
707
  v = marks?.[name.slice(5)]
577
708
  } else if (nameType === 'external-class') {
578
- name = ev.attributeName ?? ''
579
- v = elem.asGeneralComponent()?.getExternalClasses()?.[name]?.join(' ') ?? ''
709
+ const external = ev.attributeName ?? ''
710
+ const classes = elem.asGeneralComponent()?.getExternalClasses()?.[external]?.join(' ')
711
+ if (!backendUtils.classEditContext.createOrGet(external, elem)) {
712
+ name = external
713
+ v = classes ?? ''
714
+ }
580
715
  } else if (ev.attributeName === 'slot') {
581
716
  name = ev.attributeName
582
717
  v = elem.slot
@@ -584,8 +719,10 @@ export class MountPointsManager {
584
719
  name = ev.attributeName
585
720
  v = elem.id
586
721
  } else if (ev.attributeName === 'class') {
587
- name = ev.attributeName
588
- v = elem.class
722
+ if (!backendUtils.classEditContext.createOrGet('', elem).matches(elem.class)) {
723
+ name = ev.attributeName
724
+ v = elem.class
725
+ }
589
726
  } else if (ev.attributeName === 'style') {
590
727
  name = ev.attributeName
591
728
  v = elem.style
@@ -603,8 +740,6 @@ export class MountPointsManager {
603
740
  detail,
604
741
  nameType,
605
742
  })
606
- } else {
607
- warn('unknown mutation observer event')
608
743
  }
609
744
  }
610
745
  return
@@ -22,7 +22,6 @@ export type AgentRequestKind = {
22
22
  removeGlassEaselStyleSheetProperty: RemoveGlassEaselStyleSheetProperty
23
23
  replaceGlassEaselStyleSheetProperty: ReplaceGlassEaselStyleSheetProperty
24
24
  replaceGlassEaselStyleSheetAllProperties: ReplaceGlassEaselStyleSheetAllProperties
25
- replaceGlassEaselStyleSheetInlineStyle: ReplaceGlassEaselStyleSheetInlineStyle
26
25
  }
27
26
 
28
27
  export type StyleSheetId = string
@@ -47,11 +46,12 @@ export type CSSStyle = {
47
46
  }
48
47
 
49
48
  export type CSSRule = {
50
- styleSheetId?: StyleSheetId
49
+ styleSheetId: StyleSheetId
51
50
  selectorList: { selectors: { text: string }[]; text: string }
52
51
  style: CSSStyle
53
52
  media?: { styleSheetId?: StyleSheetId; text: string }[]
54
53
  inactive?: boolean
54
+ ruleIndex: number
55
55
  }
56
56
 
57
57
  export type CSSMatchedRule = {
@@ -103,7 +103,7 @@ export interface GetMatchedStylesForNode extends RequestResponse {
103
103
  * Add a new CSS rule.
104
104
  */
105
105
  export interface AddGlassEaselStyleSheetRule extends RequestResponse {
106
- request: { mediaQueryText: string; selector: string }
106
+ request: { nodeId: NodeId; mediaQueryText: string; selector: string }
107
107
  }
108
108
 
109
109
  /**
@@ -111,36 +111,43 @@ export interface AddGlassEaselStyleSheetRule extends RequestResponse {
111
111
  */
112
112
  export interface GetGlassEaselStyleSheetIndexForNewRules extends RequestResponse {
113
113
  request: Record<string, never>
114
- response: { styleSheetId: StyleSheetId }
114
+ response: { nodeId: NodeId; styleSheetId: StyleSheetId }
115
115
  }
116
116
 
117
117
  /**
118
118
  * Clear a CSS rule.
119
+ *
120
+ * `styleSheetId = undefined` refers to the inline styles.
119
121
  */
120
122
  export interface ResetGlassEaselStyleSheetRule extends RequestResponse {
121
- request: { styleSheetId: StyleSheetId; ruleIndex: number }
123
+ request: { nodeId: NodeId; styleSheetId?: StyleSheetId; ruleIndex: number }
122
124
  }
123
125
 
124
126
  /**
125
127
  * Modify the CSS rule selector.
126
128
  */
127
129
  export interface ModifyGlassEaselStyleSheetRuleSelector extends RequestResponse {
128
- request: { styleSheetId: StyleSheetId; ruleIndex: number; selector: string }
130
+ request: { nodeId: NodeId; styleSheetId: StyleSheetId; ruleIndex: number; selector: string }
129
131
  }
130
132
 
131
133
  /**
132
134
  * Add a new CSS property.
135
+ *
136
+ * `styleSheetId = undefined` refers to the inline styles.
133
137
  */
134
138
  export interface AddGlassEaselStyleSheetProperty extends RequestResponse {
135
- request: { styleSheetId: StyleSheetId; ruleIndex: number; styleText: string }
139
+ request: { nodeId: NodeId; styleSheetId?: StyleSheetId; ruleIndex: number; styleText: string }
136
140
  }
137
141
 
138
142
  /**
139
143
  * Set the disabled status of a new CSS property.
144
+ *
145
+ * `styleSheetId = undefined` refers to the inline styles.
140
146
  */
141
147
  export interface SetGlassEaselStyleSheetPropertyDisabled extends RequestResponse {
142
148
  request: {
143
- styleSheetId: StyleSheetId
149
+ nodeId: NodeId
150
+ styleSheetId?: StyleSheetId
144
151
  ruleIndex: number
145
152
  propertyIndex: number
146
153
  disabled: boolean
@@ -149,10 +156,13 @@ export interface SetGlassEaselStyleSheetPropertyDisabled extends RequestResponse
149
156
 
150
157
  /**
151
158
  * Remove a CSS property.
159
+ *
160
+ * `styleSheetId = undefined` refers to the inline styles.
152
161
  */
153
162
  export interface RemoveGlassEaselStyleSheetProperty extends RequestResponse {
154
163
  request: {
155
- styleSheetId: StyleSheetId
164
+ nodeId: NodeId
165
+ styleSheetId?: StyleSheetId
156
166
  ruleIndex: number
157
167
  propertyIndex: number
158
168
  }
@@ -160,10 +170,13 @@ export interface RemoveGlassEaselStyleSheetProperty extends RequestResponse {
160
170
 
161
171
  /**
162
172
  * Replace a CSS property.
173
+ *
174
+ * `styleSheetId = undefined` refers to the inline styles.
163
175
  */
164
176
  export interface ReplaceGlassEaselStyleSheetProperty extends RequestResponse {
165
177
  request: {
166
- styleSheetId: StyleSheetId
178
+ nodeId: NodeId
179
+ styleSheetId?: StyleSheetId
167
180
  ruleIndex: number
168
181
  propertyIndex: number
169
182
  styleText: string
@@ -172,21 +185,14 @@ export interface ReplaceGlassEaselStyleSheetProperty extends RequestResponse {
172
185
 
173
186
  /**
174
187
  * Replace all CSS properties.
188
+ *
189
+ * `styleSheetId = undefined` refers to the inline styles.
175
190
  */
176
191
  export interface ReplaceGlassEaselStyleSheetAllProperties extends RequestResponse {
177
- request: {
178
- styleSheetId: StyleSheetId
179
- ruleIndex: number
180
- styleText: string
181
- }
182
- }
183
-
184
- /**
185
- * Replace inline style for a node.
186
- */
187
- export interface ReplaceGlassEaselStyleSheetInlineStyle extends RequestResponse {
188
192
  request: {
189
193
  nodeId: NodeId
194
+ styleSheetId?: StyleSheetId
195
+ ruleIndex: number
190
196
  styleText: string
191
197
  }
192
198
  }
@@ -18,6 +18,7 @@ export type AgentRequestKind = {
18
18
  pushNodesByBackendIdsToFrontend: PushNodesByBackendIdsToFrontend
19
19
  removeAttribute: RemoveAttribute
20
20
  setAttributeValue: SetAttributeValue
21
+ setGlassEaselClassList: SetGlassEaselClassList
21
22
  setAttributesAsText: SetAttributesAsText
22
23
  getAttributes: GetAttributes
23
24
  getGlassEaselAttributes: GetGlassEaselAttributes
@@ -161,10 +162,30 @@ export interface RemoveAttribute extends RequestResponse {
161
162
  * Set an attribute.
162
163
  */
163
164
  export interface SetAttributeValue extends RequestResponse {
164
- request: { nodeId: NodeId; name: string; value: string }
165
+ request: {
166
+ nodeId: NodeId
167
+ name: string
168
+ value: string
169
+ nameType?: 'auto' | 'normal-attribute' | 'property' | 'external-class'
170
+ }
165
171
  cdpRequestResponse: [Protocol.DOM.SetAttributeValueRequest, unknown]
166
172
  }
167
173
 
174
+ /**
175
+ * Set an attribute.
176
+ */
177
+ export interface SetGlassEaselClassList extends RequestResponse {
178
+ request: {
179
+ nodeId: NodeId
180
+ externalClass?: string
181
+ classes: { className: string; disabled?: boolean }[]
182
+ }
183
+ response: {
184
+ classes: { className: string; disabled?: boolean }[]
185
+ }
186
+ cdpRequestResponse: [unknown, unknown]
187
+ }
188
+
168
189
  /**
169
190
  * Set attributes as text.
170
191
  *
@@ -197,7 +218,7 @@ export interface GetGlassEaselAttributes extends RequestResponse {
197
218
  virtual: boolean
198
219
  is: string
199
220
  id: string
200
- class: string
221
+ classes: { className: string; disabled?: boolean }[]
201
222
  slot: string
202
223
  slotName: string | undefined
203
224
  slotValues: { name: string; value: GlassEaselVar }[] | undefined
@@ -210,7 +231,7 @@ export interface GetGlassEaselAttributes extends RequestResponse {
210
231
  }[]
211
232
  normalAttributes?: { name: string; value: GlassEaselVar }[]
212
233
  properties?: { name: string; value: GlassEaselVar }[]
213
- externalClasses?: { name: string; value: string }[]
234
+ externalClasses?: { name: string; value: { className: string; disabled?: boolean }[] }[]
214
235
  dataset: { name: string; value: GlassEaselVar }[]
215
236
  marks: { name: string; value: GlassEaselVar }[]
216
237
  }