chrome-devtools-frontend 1.0.1593518 → 1.0.1593959
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.
- package/docs/contributing/settings-experiments-features.md +75 -100
- package/front_end/core/host/UserMetrics.ts +1 -2
- package/front_end/core/protocol_client/InspectorBackend.ts +4 -0
- package/front_end/core/root/ExperimentNames.ts +0 -1
- package/front_end/core/sdk/EmulationModel.ts +41 -1
- package/front_end/entrypoints/main/MainImpl.ts +0 -6
- package/front_end/generated/InspectorBackendCommands.ts +6 -4
- package/front_end/generated/protocol-mapping.d.ts +7 -0
- package/front_end/generated/protocol-proxy-api.d.ts +5 -0
- package/front_end/generated/protocol.ts +47 -0
- package/front_end/models/ai_code_completion/AiCodeCompletion.ts +1 -0
- package/front_end/models/emulation/DeviceModeModel.ts +47 -0
- package/front_end/models/issues_manager/IssueAggregator.ts +0 -9
- package/front_end/models/issues_manager/IssuesManager.ts +0 -5
- package/front_end/models/issues_manager/issues_manager.ts +0 -4
- package/front_end/models/javascript_metadata/NativeFunctions.js +4 -0
- package/front_end/models/lighthouse/lighthouse.ts +9 -0
- package/front_end/panels/common/AiCodeCompletionDisclaimer.ts +3 -0
- package/front_end/panels/common/AiCodeGenerationTeaser.ts +3 -0
- package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +1 -6
- package/front_end/panels/elements/StylesSidebarPane.ts +79 -0
- package/front_end/panels/emulation/DeviceModeToolbar.ts +206 -66
- package/front_end/panels/issues/HiddenIssuesRow.ts +1 -1
- package/front_end/panels/issues/IssueKindView.ts +2 -1
- package/front_end/panels/issues/IssueView.ts +2 -4
- package/front_end/panels/issues/IssuesPane.ts +2 -2
- package/front_end/panels/lighthouse/LighthouseController.ts +3 -3
- package/front_end/panels/lighthouse/LighthousePanel.ts +9 -5
- package/front_end/panels/lighthouse/LighthouseProtocolService.ts +5 -5
- package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +6 -7
- package/front_end/panels/lighthouse/LighthouseReportSelector.ts +4 -3
- package/front_end/panels/lighthouse/lighthouse.ts +0 -2
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/deno.json +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/package.json +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.js +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.ts +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.js +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.js.map +1 -1
- package/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.ts +2 -2
- package/front_end/ui/legacy/SuggestBox.ts +4 -0
- package/front_end/ui/legacy/TextPrompt.ts +1 -1
- package/front_end/ui/visual_logging/KnownContextValues.ts +15 -0
- package/inspector_overlay/highlight_grid_common.ts +11 -8
- package/package.json +1 -1
- package/front_end/models/issues_manager/ContrastCheckTrigger.ts +0 -78
- package/front_end/models/issues_manager/LowTextContrastIssue.ts +0 -63
- package/front_end/panels/issues/AffectedElementsWithLowContrastView.ts +0 -91
- /package/front_end/{panels → models}/lighthouse/LighthouseReporterTypes.ts +0 -0
|
@@ -1221,6 +1221,7 @@ export namespace Audits {
|
|
|
1221
1221
|
AutofillAndManualTextPolicyControlledFeaturesInfo = 'AutofillAndManualTextPolicyControlledFeaturesInfo',
|
|
1222
1222
|
AutofillPolicyControlledFeatureInfo = 'AutofillPolicyControlledFeatureInfo',
|
|
1223
1223
|
ManualTextPolicyControlledFeatureInfo = 'ManualTextPolicyControlledFeatureInfo',
|
|
1224
|
+
FormModelContextParameterMissingTitleAndDescription = 'FormModelContextParameterMissingTitleAndDescription',
|
|
1224
1225
|
}
|
|
1225
1226
|
|
|
1226
1227
|
/**
|
|
@@ -3033,6 +3034,11 @@ export namespace CSS {
|
|
|
3033
3034
|
* The array enumerates @starting-style at-rules starting with the innermost one, going outwards.
|
|
3034
3035
|
*/
|
|
3035
3036
|
startingStyles?: CSSStartingStyle[];
|
|
3037
|
+
/**
|
|
3038
|
+
* @navigation CSS at-rule array.
|
|
3039
|
+
* The array enumerates @navigation at-rules starting with the innermost one, going outwards.
|
|
3040
|
+
*/
|
|
3041
|
+
navigations?: CSSNavigation[];
|
|
3036
3042
|
}
|
|
3037
3043
|
|
|
3038
3044
|
/**
|
|
@@ -3047,6 +3053,7 @@ export namespace CSS {
|
|
|
3047
3053
|
ScopeRule = 'ScopeRule',
|
|
3048
3054
|
StyleRule = 'StyleRule',
|
|
3049
3055
|
StartingStyleRule = 'StartingStyleRule',
|
|
3056
|
+
NavigationRule = 'NavigationRule',
|
|
3050
3057
|
}
|
|
3051
3058
|
|
|
3052
3059
|
/**
|
|
@@ -3342,6 +3349,29 @@ export namespace CSS {
|
|
|
3342
3349
|
styleSheetId?: DOM.StyleSheetId;
|
|
3343
3350
|
}
|
|
3344
3351
|
|
|
3352
|
+
/**
|
|
3353
|
+
* CSS Navigation at-rule descriptor.
|
|
3354
|
+
*/
|
|
3355
|
+
export interface CSSNavigation {
|
|
3356
|
+
/**
|
|
3357
|
+
* Navigation rule text.
|
|
3358
|
+
*/
|
|
3359
|
+
text: string;
|
|
3360
|
+
/**
|
|
3361
|
+
* Whether the navigation condition is satisfied.
|
|
3362
|
+
*/
|
|
3363
|
+
active?: boolean;
|
|
3364
|
+
/**
|
|
3365
|
+
* The associated rule header range in the enclosing stylesheet (if
|
|
3366
|
+
* available).
|
|
3367
|
+
*/
|
|
3368
|
+
range?: SourceRange;
|
|
3369
|
+
/**
|
|
3370
|
+
* Identifier of the stylesheet containing this object (if exists).
|
|
3371
|
+
*/
|
|
3372
|
+
styleSheetId?: DOM.StyleSheetId;
|
|
3373
|
+
}
|
|
3374
|
+
|
|
3345
3375
|
/**
|
|
3346
3376
|
* CSS Scope at-rule descriptor.
|
|
3347
3377
|
*/
|
|
@@ -3676,6 +3706,10 @@ export namespace CSS {
|
|
|
3676
3706
|
* @supports CSS at-rule condition. Only one type of condition should be set.
|
|
3677
3707
|
*/
|
|
3678
3708
|
supports?: CSSSupports;
|
|
3709
|
+
/**
|
|
3710
|
+
* @navigation condition. Only one type of condition should be set.
|
|
3711
|
+
*/
|
|
3712
|
+
navigation?: CSSNavigation;
|
|
3679
3713
|
/**
|
|
3680
3714
|
* Block body.
|
|
3681
3715
|
*/
|
|
@@ -4165,6 +4199,19 @@ export namespace CSS {
|
|
|
4165
4199
|
supports: CSSSupports;
|
|
4166
4200
|
}
|
|
4167
4201
|
|
|
4202
|
+
export interface SetNavigationTextRequest {
|
|
4203
|
+
styleSheetId: DOM.StyleSheetId;
|
|
4204
|
+
range: SourceRange;
|
|
4205
|
+
text: string;
|
|
4206
|
+
}
|
|
4207
|
+
|
|
4208
|
+
export interface SetNavigationTextResponse extends ProtocolResponseWithError {
|
|
4209
|
+
/**
|
|
4210
|
+
* The resulting CSS Navigation rule after modification.
|
|
4211
|
+
*/
|
|
4212
|
+
navigation: CSSNavigation;
|
|
4213
|
+
}
|
|
4214
|
+
|
|
4168
4215
|
export interface SetScopeTextRequest {
|
|
4169
4216
|
styleSheetId: DOM.StyleSheetId;
|
|
4170
4217
|
range: SourceRange;
|
|
@@ -113,6 +113,7 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
113
113
|
#emulationModel: SDK.EmulationModel.EmulationModel|null;
|
|
114
114
|
#onModelAvailable: (() => void)|null;
|
|
115
115
|
#outlineRect?: Rect;
|
|
116
|
+
#screenOrientationLocked: boolean;
|
|
116
117
|
|
|
117
118
|
private constructor() {
|
|
118
119
|
super();
|
|
@@ -172,6 +173,7 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
172
173
|
|
|
173
174
|
this.#emulationModel = null;
|
|
174
175
|
this.#onModelAvailable = null;
|
|
176
|
+
this.#screenOrientationLocked = false;
|
|
175
177
|
SDK.TargetManager.TargetManager.instance().observeModels(SDK.EmulationModel.EmulationModel, this);
|
|
176
178
|
}
|
|
177
179
|
|
|
@@ -442,6 +444,9 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
442
444
|
this.#onModelAvailable = null;
|
|
443
445
|
callback();
|
|
444
446
|
}
|
|
447
|
+
emulationModel.addEventListener(
|
|
448
|
+
SDK.EmulationModel.EmulationModelEvents.SCREEN_ORIENTATION_LOCK_CHANGED, this.onScreenOrientationLockChanged,
|
|
449
|
+
this);
|
|
445
450
|
const resourceTreeModel = emulationModel.target().model(SDK.ResourceTreeModel.ResourceTreeModel);
|
|
446
451
|
if (resourceTreeModel) {
|
|
447
452
|
resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.FrameResized, this.onFrameChange, this);
|
|
@@ -454,7 +459,12 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
454
459
|
|
|
455
460
|
modelRemoved(emulationModel: SDK.EmulationModel.EmulationModel): void {
|
|
456
461
|
if (this.#emulationModel === emulationModel) {
|
|
462
|
+
emulationModel.removeEventListener(
|
|
463
|
+
SDK.EmulationModel.EmulationModelEvents.SCREEN_ORIENTATION_LOCK_CHANGED, this.onScreenOrientationLockChanged,
|
|
464
|
+
this);
|
|
457
465
|
this.#emulationModel = null;
|
|
466
|
+
this.#screenOrientationLocked = false;
|
|
467
|
+
this.dispatchEventToListeners(Events.UPDATED);
|
|
458
468
|
}
|
|
459
469
|
}
|
|
460
470
|
|
|
@@ -471,6 +481,43 @@ export class DeviceModeModel extends Common.ObjectWrapper.ObjectWrapper<EventTyp
|
|
|
471
481
|
this.showHingeIfApplicable(overlayModel);
|
|
472
482
|
}
|
|
473
483
|
|
|
484
|
+
private onScreenOrientationLockChanged(
|
|
485
|
+
event: Common.EventTarget.EventTargetEvent<SDK.EmulationModel.ScreenOrientationLockChangedEvent>): void {
|
|
486
|
+
this.#screenOrientationLocked = event.data.locked;
|
|
487
|
+
if (event.data.locked && event.data.orientation) {
|
|
488
|
+
this.applyOrientationLock(event.data.orientation);
|
|
489
|
+
}
|
|
490
|
+
this.dispatchEventToListeners(Events.UPDATED);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
private applyOrientationLock(orientation: Protocol.Emulation.ScreenOrientation): void {
|
|
494
|
+
const wantsLandscape = orientation.type === Protocol.Emulation.ScreenOrientationType.LandscapePrimary ||
|
|
495
|
+
orientation.type === Protocol.Emulation.ScreenOrientationType.LandscapeSecondary;
|
|
496
|
+
|
|
497
|
+
if (this.#type === Type.Device && this.#device && this.#mode) {
|
|
498
|
+
// For device emulation, switch to the matching orientation mode.
|
|
499
|
+
const isCurrentlyLandscape =
|
|
500
|
+
this.#mode.orientation === Horizontal || this.#mode.orientation === HorizontalSpanned;
|
|
501
|
+
if (wantsLandscape !== isCurrentlyLandscape) {
|
|
502
|
+
const rotationPartner = this.#device.getRotationPartner(this.#mode);
|
|
503
|
+
if (rotationPartner) {
|
|
504
|
+
this.emulate(this.#type, this.#device, rotationPartner);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
} else if (this.#type === Type.Responsive) {
|
|
508
|
+
// For responsive mode, swap width/height if orientation doesn't match.
|
|
509
|
+
const appliedSize = this.appliedDeviceSize();
|
|
510
|
+
const isCurrentlyLandscape = appliedSize.width > appliedSize.height;
|
|
511
|
+
if (wantsLandscape !== isCurrentlyLandscape) {
|
|
512
|
+
this.setSizeAndScaleToFit(appliedSize.height, appliedSize.width);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
isScreenOrientationLocked(): boolean {
|
|
518
|
+
return this.#screenOrientationLocked;
|
|
519
|
+
}
|
|
520
|
+
|
|
474
521
|
private scaleSettingChanged(): void {
|
|
475
522
|
this.calculateAndEmulate(false);
|
|
476
523
|
}
|
|
@@ -17,7 +17,6 @@ import {HeavyAdIssue} from './HeavyAdIssue.js';
|
|
|
17
17
|
import {Issue, IssueCategory, IssueKind, unionIssueKind} from './Issue.js';
|
|
18
18
|
import type {EventTypes as IssuesManagerEventsTypes, IssueAddedEvent} from './IssuesManager.js';
|
|
19
19
|
import {Events as IssuesManagerEvents} from './IssuesManagerEvents.js';
|
|
20
|
-
import {LowTextContrastIssue} from './LowTextContrastIssue.js';
|
|
21
20
|
import type {MarkdownIssueDescription} from './MarkdownIssueDescription.js';
|
|
22
21
|
import {MixedContentIssue} from './MixedContentIssue.js';
|
|
23
22
|
import {PartitioningBlobURLIssue} from './PartitioningBlobURLIssue.js';
|
|
@@ -64,7 +63,6 @@ export class AggregatedIssue extends Issue {
|
|
|
64
63
|
#cspIssues = new Set<ContentSecurityPolicyIssue>();
|
|
65
64
|
#deprecationIssues = new Set<DeprecationIssue>();
|
|
66
65
|
#issueKind = IssueKind.IMPROVEMENT;
|
|
67
|
-
#lowContrastIssues = new Set<LowTextContrastIssue>();
|
|
68
66
|
#cookieDeprecationMetadataIssues = new Set<CookieDeprecationMetadataIssue>();
|
|
69
67
|
#mixedContentIssues = new Set<MixedContentIssue>();
|
|
70
68
|
#partitioningBlobURLIssues = new Set<PartitioningBlobURLIssue>();
|
|
@@ -142,10 +140,6 @@ export class AggregatedIssue extends Issue {
|
|
|
142
140
|
return this.#deprecationIssues;
|
|
143
141
|
}
|
|
144
142
|
|
|
145
|
-
getLowContrastIssues(): Iterable<LowTextContrastIssue> {
|
|
146
|
-
return this.#lowContrastIssues;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
143
|
override requests(): Iterable<Protocol.Audits.AffectedRequest> {
|
|
150
144
|
return this.#affectedRequests.values();
|
|
151
145
|
}
|
|
@@ -267,9 +261,6 @@ export class AggregatedIssue extends Issue {
|
|
|
267
261
|
if (issue instanceof SharedArrayBufferIssue) {
|
|
268
262
|
this.#sharedArrayBufferIssues.add(issue);
|
|
269
263
|
}
|
|
270
|
-
if (issue instanceof LowTextContrastIssue) {
|
|
271
|
-
this.#lowContrastIssues.add(issue);
|
|
272
|
-
}
|
|
273
264
|
if (issue instanceof CorsIssue) {
|
|
274
265
|
this.#corsIssues.add(issue);
|
|
275
266
|
}
|
|
@@ -22,7 +22,6 @@ import {GenericIssue} from './GenericIssue.js';
|
|
|
22
22
|
import {HeavyAdIssue} from './HeavyAdIssue.js';
|
|
23
23
|
import type {Issue, IssueKind} from './Issue.js';
|
|
24
24
|
import {Events} from './IssuesManagerEvents.js';
|
|
25
|
-
import {LowTextContrastIssue} from './LowTextContrastIssue.js';
|
|
26
25
|
import {MixedContentIssue} from './MixedContentIssue.js';
|
|
27
26
|
import {PartitioningBlobURLIssue} from './PartitioningBlobURLIssue.js';
|
|
28
27
|
import {PermissionElementIssue} from './PermissionElementIssue.js';
|
|
@@ -81,10 +80,6 @@ const issueCodeHandlers = new Map<
|
|
|
81
80
|
Protocol.Audits.InspectorIssueCode.SharedDictionaryIssue,
|
|
82
81
|
SharedDictionaryIssue.fromInspectorIssue,
|
|
83
82
|
],
|
|
84
|
-
[
|
|
85
|
-
Protocol.Audits.InspectorIssueCode.LowTextContrastIssue,
|
|
86
|
-
LowTextContrastIssue.fromInspectorIssue,
|
|
87
|
-
],
|
|
88
83
|
[
|
|
89
84
|
Protocol.Audits.InspectorIssueCode.CorsIssue,
|
|
90
85
|
CorsIssue.fromInspectorIssue,
|
|
@@ -7,7 +7,6 @@ import * as CheckFormsIssuesTrigger from './CheckFormsIssuesTrigger.js';
|
|
|
7
7
|
import * as ClientHintIssue from './ClientHintIssue.js';
|
|
8
8
|
import * as ConnectionAllowlistIssue from './ConnectionAllowlistIssue.js';
|
|
9
9
|
import * as ContentSecurityPolicyIssue from './ContentSecurityPolicyIssue.js';
|
|
10
|
-
import * as ContrastCheckTrigger from './ContrastCheckTrigger.js';
|
|
11
10
|
import * as CookieDeprecationMetadataIssue from './CookieDeprecationMetadataIssue.js';
|
|
12
11
|
import * as CookieIssue from './CookieIssue.js';
|
|
13
12
|
import * as CorsIssue from './CorsIssue.js';
|
|
@@ -21,7 +20,6 @@ import * as Issue from './Issue.js';
|
|
|
21
20
|
import * as IssueAggregator from './IssueAggregator.js';
|
|
22
21
|
import * as IssueResolver from './IssueResolver.js';
|
|
23
22
|
import * as IssuesManager from './IssuesManager.js';
|
|
24
|
-
import * as LowTextContrastIssue from './LowTextContrastIssue.js';
|
|
25
23
|
import * as MarkdownIssueDescription from './MarkdownIssueDescription.js';
|
|
26
24
|
import * as MixedContentIssue from './MixedContentIssue.js';
|
|
27
25
|
import * as PartitioningBlobURLIssue from './PartitioningBlobURLIssue.js';
|
|
@@ -42,7 +40,6 @@ export {
|
|
|
42
40
|
ClientHintIssue,
|
|
43
41
|
ConnectionAllowlistIssue,
|
|
44
42
|
ContentSecurityPolicyIssue,
|
|
45
|
-
ContrastCheckTrigger,
|
|
46
43
|
CookieDeprecationMetadataIssue,
|
|
47
44
|
CookieIssue,
|
|
48
45
|
CorsIssue,
|
|
@@ -56,7 +53,6 @@ export {
|
|
|
56
53
|
IssueAggregator,
|
|
57
54
|
IssueResolver,
|
|
58
55
|
IssuesManager,
|
|
59
|
-
LowTextContrastIssue,
|
|
60
56
|
MarkdownIssueDescription,
|
|
61
57
|
MixedContentIssue,
|
|
62
58
|
PartitioningBlobURLIssue,
|
|
@@ -7221,6 +7221,10 @@ export const NativeFunctions = [
|
|
|
7221
7221
|
name: "OffscreenCanvas",
|
|
7222
7222
|
signatures: [["width","height"]]
|
|
7223
7223
|
},
|
|
7224
|
+
{
|
|
7225
|
+
name: "OverscrollEvent",
|
|
7226
|
+
signatures: [["type","?eventInitDict"]]
|
|
7227
|
+
},
|
|
7224
7228
|
{
|
|
7225
7229
|
name: "setValueAndClosePopup",
|
|
7226
7230
|
signatures: [["numberValue","stringValue","is_keyboard_event"]]
|
|
@@ -70,6 +70,9 @@ function getTooltipDisclaimerText(noLogging: boolean, panel: AiCodeCompletion.Ai
|
|
|
70
70
|
return noLogging ?
|
|
71
71
|
lockedString(UIStringsNotTranslate.tooltipDisclaimerTextForAiCodeCompletionNoLoggingInSources) :
|
|
72
72
|
lockedString(UIStringsNotTranslate.tooltipDisclaimerTextForAiCodeCompletionInSources);
|
|
73
|
+
case AiCodeCompletion.AiCodeCompletion.ContextFlavor.STYLES:
|
|
74
|
+
// TODO(476101019): update with string for styles pane
|
|
75
|
+
return '';
|
|
73
76
|
}
|
|
74
77
|
}
|
|
75
78
|
|
|
@@ -147,6 +147,9 @@ function getTooltipDisclaimerText(noLogging: boolean, panel: AiCodeCompletion.Ai
|
|
|
147
147
|
return noLogging ?
|
|
148
148
|
lockedString(UIStringsNotTranslate.tooltipDisclaimerTextForAiCodeGenerationNoLoggingInSources) :
|
|
149
149
|
lockedString(UIStringsNotTranslate.tooltipDisclaimerTextForAiCodeGenerationInSources);
|
|
150
|
+
case AiCodeCompletion.AiCodeCompletion.ContextFlavor.STYLES:
|
|
151
|
+
// TODO(476101019): update with string for styles pane
|
|
152
|
+
return '';
|
|
150
153
|
}
|
|
151
154
|
}
|
|
152
155
|
|
|
@@ -18,11 +18,6 @@ export class StylesAiCodeCompletionProvider {
|
|
|
18
18
|
|
|
19
19
|
#boundOnUpdateAiCodeCompletionState = this.#updateAiCodeCompletionState.bind(this);
|
|
20
20
|
|
|
21
|
-
#debouncedRequestAidaSuggestion =
|
|
22
|
-
Common.Debouncer.debounce((prefix: string, suffix: string, cursorPositionAtRequest: number) => {
|
|
23
|
-
void this.#requestAidaSuggestion(prefix, suffix, cursorPositionAtRequest);
|
|
24
|
-
}, TextEditor.AiCodeCompletionProvider.AIDA_REQUEST_DEBOUNCE_TIMEOUT_MS);
|
|
25
|
-
|
|
26
21
|
private constructor(aiCodeCompletionConfig: TextEditor.AiCodeCompletionProvider.AiCodeCompletionConfig) {
|
|
27
22
|
const devtoolsLocale = i18n.DevToolsLocale.DevToolsLocale.instance();
|
|
28
23
|
if (!AiCodeCompletion.AiCodeCompletion.AiCodeCompletion.isAiCodeCompletionStylesEnabled(devtoolsLocale.locale)) {
|
|
@@ -113,7 +108,7 @@ export class StylesAiCodeCompletionProvider {
|
|
|
113
108
|
prefix = prefix + text;
|
|
114
109
|
const suffix = content.substring(propertyEndOffset);
|
|
115
110
|
// TODO(b/476098133): Consider adjusting cursor position
|
|
116
|
-
this.#
|
|
111
|
+
await this.#requestAidaSuggestion(prefix, suffix, cursorPosition);
|
|
117
112
|
}
|
|
118
113
|
|
|
119
114
|
async #requestAidaSuggestion(prefix: string, suffix: string, cursorPositionAtRequest: number): Promise<void> {
|
|
@@ -42,9 +42,11 @@ import {assertNotNullOrUndefined} from '../../core/platform/platform.js';
|
|
|
42
42
|
import * as Root from '../../core/root/root.js';
|
|
43
43
|
import * as SDK from '../../core/sdk/sdk.js';
|
|
44
44
|
import * as Protocol from '../../generated/protocol.js';
|
|
45
|
+
import * as AiCodeCompletion from '../../models/ai_code_completion/ai_code_completion.js';
|
|
45
46
|
import * as Bindings from '../../models/bindings/bindings.js';
|
|
46
47
|
import type * as ComputedStyle from '../../models/computed_style/computed_style.js';
|
|
47
48
|
import * as TextUtils from '../../models/text_utils/text_utils.js';
|
|
49
|
+
import * as TextEditor from '../../ui/components/text_editor/text_editor.js';
|
|
48
50
|
import {createIcon, Icon} from '../../ui/kit/kit.js';
|
|
49
51
|
import * as InlineEditor from '../../ui/legacy/components/inline_editor/inline_editor.js';
|
|
50
52
|
import * as Components from '../../ui/legacy/components/utils/utils.js';
|
|
@@ -70,6 +72,7 @@ import {
|
|
|
70
72
|
} from './StylePropertiesSection.js';
|
|
71
73
|
import {StylePropertyHighlighter} from './StylePropertyHighlighter.js';
|
|
72
74
|
import type {StylePropertyTreeElement} from './StylePropertyTreeElement.js';
|
|
75
|
+
import * as StylesAiCodeCompletionProvider from './StylesAiCodeCompletionProvider.js';
|
|
73
76
|
import type {StylesContainer} from './StylesContainer.js';
|
|
74
77
|
import stylesSidebarPaneStyles from './stylesSidebarPane.css.js';
|
|
75
78
|
import {WebCustomData} from './WebCustomData.js';
|
|
@@ -1736,6 +1739,12 @@ export class CSSPropertyPrompt extends UI.TextPrompt.TextPrompt {
|
|
|
1736
1739
|
private treeElement: StylePropertyTreeElement;
|
|
1737
1740
|
private isEditingName: boolean;
|
|
1738
1741
|
private readonly cssVariables: string[];
|
|
1742
|
+
aiCodeCompletionConfig?: TextEditor.AiCodeCompletionProvider.AiCodeCompletionConfig;
|
|
1743
|
+
aiCodeCompletionProvider?: StylesAiCodeCompletionProvider.StylesAiCodeCompletionProvider;
|
|
1744
|
+
|
|
1745
|
+
#debouncedTriggerAiCodeCompletion = Common.Debouncer.debounce(() => {
|
|
1746
|
+
void this.triggerAiCodeCompletion();
|
|
1747
|
+
}, TextEditor.AiCodeCompletionProvider.AIDA_REQUEST_DEBOUNCE_TIMEOUT_MS);
|
|
1739
1748
|
|
|
1740
1749
|
constructor(treeElement: StylePropertyTreeElement, isEditingName: boolean, completions: string[] = []) {
|
|
1741
1750
|
// Use the same callback both for applyItemCallback and acceptItemCallback.
|
|
@@ -1794,6 +1803,27 @@ export class CSSPropertyPrompt extends UI.TextPrompt.TextPrompt {
|
|
|
1794
1803
|
}
|
|
1795
1804
|
}
|
|
1796
1805
|
}
|
|
1806
|
+
|
|
1807
|
+
const devtoolsLocale = i18n.DevToolsLocale.DevToolsLocale.instance();
|
|
1808
|
+
if (AiCodeCompletion.AiCodeCompletion.AiCodeCompletion.isAiCodeCompletionStylesEnabled(devtoolsLocale.locale)) {
|
|
1809
|
+
this.aiCodeCompletionConfig = {
|
|
1810
|
+
completionContext: {},
|
|
1811
|
+
generationContext: {},
|
|
1812
|
+
onFeatureEnabled: () => {},
|
|
1813
|
+
onFeatureDisabled: () => {},
|
|
1814
|
+
onSuggestionAccepted: () => {},
|
|
1815
|
+
onRequestTriggered: () => {},
|
|
1816
|
+
onResponseReceived: () => {},
|
|
1817
|
+
panel: AiCodeCompletion.AiCodeCompletion.ContextFlavor.STYLES,
|
|
1818
|
+
getCompletionHint: this.getCompletionHint.bind(this),
|
|
1819
|
+
getCurrentText: () => {
|
|
1820
|
+
return this.text();
|
|
1821
|
+
},
|
|
1822
|
+
setAiAutoCompletion: () => {},
|
|
1823
|
+
};
|
|
1824
|
+
this.aiCodeCompletionProvider =
|
|
1825
|
+
StylesAiCodeCompletionProvider.StylesAiCodeCompletionProvider.createInstance(this.aiCodeCompletionConfig);
|
|
1826
|
+
}
|
|
1797
1827
|
}
|
|
1798
1828
|
|
|
1799
1829
|
override onKeyDown(event: Event): void {
|
|
@@ -1844,6 +1874,13 @@ export class CSSPropertyPrompt extends UI.TextPrompt.TextPrompt {
|
|
|
1844
1874
|
return false;
|
|
1845
1875
|
}
|
|
1846
1876
|
|
|
1877
|
+
override onInput(event: Event): void {
|
|
1878
|
+
super.onInput(event);
|
|
1879
|
+
if (this.aiCodeCompletionProvider) {
|
|
1880
|
+
this.#debouncedTriggerAiCodeCompletion();
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1847
1884
|
private handleNameOrValueUpDown(event: Event): boolean {
|
|
1848
1885
|
function finishHandler(this: CSSPropertyPrompt, _originalValue: string, _replacementString: string): void {
|
|
1849
1886
|
// Synthesize property text disregarding any comments, custom whitespace etc.
|
|
@@ -2054,6 +2091,48 @@ export class CSSPropertyPrompt extends UI.TextPrompt.TextPrompt {
|
|
|
2054
2091
|
return subtitleElement;
|
|
2055
2092
|
}
|
|
2056
2093
|
}
|
|
2094
|
+
|
|
2095
|
+
private async triggerAiCodeCompletion(): Promise<void> {
|
|
2096
|
+
const selection = this.element().getComponentSelection();
|
|
2097
|
+
if (!this.aiCodeCompletionProvider || !selection || selection.rangeCount === 0) {
|
|
2098
|
+
return;
|
|
2099
|
+
}
|
|
2100
|
+
const range = selection.getRangeAt(0);
|
|
2101
|
+
const userInput = this.text();
|
|
2102
|
+
// Only trigger if caret is at end of text content
|
|
2103
|
+
if (range.endOffset < userInput.length) {
|
|
2104
|
+
return;
|
|
2105
|
+
}
|
|
2106
|
+
const cssModel = this.treeElement.stylesContainer().cssModel();
|
|
2107
|
+
if (!cssModel) {
|
|
2108
|
+
return;
|
|
2109
|
+
}
|
|
2110
|
+
await this.aiCodeCompletionProvider.triggerAiCodeCompletion(
|
|
2111
|
+
userInput, range.endOffset, this.isEditingName, this.treeElement.property, cssModel);
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
/**
|
|
2115
|
+
* Extracts the remaining portion of the suggestion text that follows the
|
|
2116
|
+
* user's current input.
|
|
2117
|
+
*/
|
|
2118
|
+
private getCompletionHint(): string|null {
|
|
2119
|
+
const topSuggestion = this.isSuggestBoxVisible() ? this.suggestBox?.completion() : null;
|
|
2120
|
+
const suggestionText = topSuggestion?.text;
|
|
2121
|
+
if (!suggestionText) {
|
|
2122
|
+
return null;
|
|
2123
|
+
}
|
|
2124
|
+
const userInput = this.text();
|
|
2125
|
+
let completionHint = suggestionText;
|
|
2126
|
+
// Iterate from the longest possible overlap down to the shortest
|
|
2127
|
+
for (let i = Math.min(userInput.length, suggestionText.length); i > 0; i--) {
|
|
2128
|
+
const overlapCandidate = suggestionText.substring(0, i);
|
|
2129
|
+
if (userInput.endsWith(overlapCandidate)) {
|
|
2130
|
+
completionHint = suggestionText.slice(i);
|
|
2131
|
+
break;
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
return completionHint;
|
|
2135
|
+
}
|
|
2057
2136
|
}
|
|
2058
2137
|
|
|
2059
2138
|
export function unescapeCssString(input: string): string {
|