chrome-devtools-frontend 1.0.1030070 → 1.0.1031400

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.
Files changed (81) hide show
  1. package/config/gni/devtools_grd_files.gni +3 -0
  2. package/config/gni/devtools_image_files.gni +2 -0
  3. package/docs/workflows.md +1 -1
  4. package/front_end/Images/src/file-sync_icon.svg +62 -0
  5. package/front_end/Images/src/file_icon.svg +52 -0
  6. package/front_end/Tests.js +0 -28
  7. package/front_end/core/host/UserMetrics.ts +2 -1
  8. package/front_end/core/i18n/locales/en-US.json +18 -9
  9. package/front_end/core/i18n/locales/en-XL.json +18 -9
  10. package/front_end/core/platform/string-utilities.ts +2 -5
  11. package/front_end/core/root/Runtime.ts +1 -0
  12. package/front_end/core/sdk/CSSStyleSheetHeader.ts +0 -4
  13. package/front_end/core/sdk/CompilerSourceMappingContentProvider.ts +0 -4
  14. package/front_end/core/sdk/NetworkRequest.ts +0 -4
  15. package/front_end/core/sdk/Resource.ts +0 -5
  16. package/front_end/core/sdk/Script.ts +71 -76
  17. package/front_end/core/sdk/Target.ts +4 -0
  18. package/front_end/entrypoints/inspector_main/InspectorMain.ts +4 -1
  19. package/front_end/entrypoints/main/MainImpl.ts +4 -0
  20. package/front_end/generated/InspectorBackendCommands.js +10 -8
  21. package/front_end/generated/protocol-mapping.d.ts +16 -2
  22. package/front_end/generated/protocol-proxy-api.d.ts +11 -1
  23. package/front_end/generated/protocol.ts +75 -1
  24. package/front_end/models/bindings/CompilerScriptMapping.ts +6 -3
  25. package/front_end/models/bindings/ContentProviderBasedProject.ts +2 -3
  26. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +1 -4
  27. package/front_end/models/bindings/IgnoreListManager.ts +10 -8
  28. package/front_end/models/bindings/ResourceMapping.ts +0 -4
  29. package/front_end/models/bindings/StylesSourceMapping.ts +0 -5
  30. package/front_end/models/extensions/ExtensionServer.ts +2 -3
  31. package/front_end/models/issues_manager/AttributionReportingIssue.ts +8 -0
  32. package/front_end/models/issues_manager/DeprecationIssue.ts +5 -1
  33. package/front_end/models/issues_manager/descriptions/arTooManyConcurrentRequests.md +5 -0
  34. package/front_end/models/javascript_metadata/NativeFunctions.js +6 -2
  35. package/front_end/models/persistence/NetworkPersistenceManager.ts +4 -6
  36. package/front_end/models/persistence/PersistenceActions.ts +5 -4
  37. package/front_end/models/text_utils/CodeMirrorUtils.ts +17 -4
  38. package/front_end/models/text_utils/ContentProvider.ts +0 -1
  39. package/front_end/models/text_utils/StaticContentProvider.ts +0 -4
  40. package/front_end/models/workspace/UISourceCode.ts +10 -5
  41. package/front_end/panels/application/components/StackTrace.ts +2 -2
  42. package/front_end/panels/elements/CSSRuleValidator.ts +382 -63
  43. package/front_end/panels/elements/CSSRuleValidatorHelper.ts +34 -0
  44. package/front_end/panels/elements/ElementsTreeOutline.ts +23 -7
  45. package/front_end/panels/elements/StylePropertyTreeElement.ts +1 -1
  46. package/front_end/panels/elements/TopLayerContainer.ts +17 -28
  47. package/front_end/panels/elements/components/CSSHintDetailsView.ts +23 -20
  48. package/front_end/panels/elements/components/cssHintDetailsView.css +8 -2
  49. package/front_end/panels/elements/stylesSectionTree.css +1 -1
  50. package/front_end/panels/issues/AttributionReportingIssueDetailsView.ts +12 -0
  51. package/front_end/panels/network/components/RequestHeadersView.css +41 -8
  52. package/front_end/panels/network/components/RequestHeadersView.ts +102 -12
  53. package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +1 -0
  54. package/front_end/panels/sources/FilteredUISourceCodeListProvider.ts +7 -0
  55. package/front_end/panels/sources/NavigatorView.ts +22 -0
  56. package/front_end/panels/sources/ScopeChainSidebarPane.ts +3 -3
  57. package/front_end/third_party/codemirror.next/bundle.ts +1 -1
  58. package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
  59. package/front_end/third_party/codemirror.next/chunk/cpp.js +1 -2
  60. package/front_end/third_party/codemirror.next/chunk/java.js +1 -2
  61. package/front_end/third_party/codemirror.next/chunk/json.js +1 -2
  62. package/front_end/third_party/codemirror.next/chunk/markdown.js +1 -2
  63. package/front_end/third_party/codemirror.next/chunk/php.js +1 -2
  64. package/front_end/third_party/codemirror.next/chunk/python.js +1 -2
  65. package/front_end/third_party/codemirror.next/chunk/wast.js +1 -2
  66. package/front_end/third_party/codemirror.next/chunk/xml.js +1 -2
  67. package/front_end/third_party/codemirror.next/codemirror.next.d.ts +1247 -116
  68. package/front_end/third_party/codemirror.next/codemirror.next.js +1 -2
  69. package/front_end/ui/components/data_grid/DataGrid.ts +15 -10
  70. package/front_end/ui/components/data_grid/DataGridController.ts +7 -0
  71. package/front_end/ui/components/docs/building-ui-documentation/StylingComponents.md +64 -0
  72. package/front_end/ui/components/linear_memory_inspector/LinearMemoryInspector.ts +2 -3
  73. package/front_end/ui/components/linear_memory_inspector/LinearMemoryInspectorController.ts +97 -17
  74. package/front_end/ui/components/linear_memory_inspector/LinearMemoryInspectorPane.ts +1 -1
  75. package/front_end/ui/components/linear_memory_inspector/LinearMemoryViewerUtils.ts +4 -0
  76. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +9 -7
  77. package/front_end/ui/legacy/components/source_frame/ImageView.ts +10 -11
  78. package/front_end/ui/legacy/components/source_frame/PreviewFactory.ts +1 -1
  79. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +49 -0
  80. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +18 -17
  81. package/package.json +6 -5
@@ -54,12 +54,13 @@ export class ContextMenuProvider implements UI.ContextMenu.Provider {
54
54
  if (contentProvider instanceof Workspace.UISourceCode.UISourceCode) {
55
55
  (contentProvider as Workspace.UISourceCode.UISourceCode).commitWorkingCopy();
56
56
  }
57
- let content: string = (await contentProvider.requestContent()).content || '';
58
- if (await contentProvider.contentEncoded()) {
59
- content = window.atob(content);
57
+ const content = await contentProvider.requestContent();
58
+ let decodedContent = content.content || '';
59
+ if (content.isEncoded) {
60
+ decodedContent = window.atob(decodedContent);
60
61
  }
61
62
  const url = contentProvider.contentURL();
62
- void Workspace.FileManager.FileManager.instance().save(url, content as string, true);
63
+ void Workspace.FileManager.FileManager.instance().save(url, decodedContent, true);
63
64
  Workspace.FileManager.FileManager.instance().close(url);
64
65
  }
65
66
 
@@ -37,12 +37,25 @@ export function createCssTokenizer(): Tokenizer {
37
37
  const stream = new CodeMirror.StringStream();
38
38
  stream.string = line;
39
39
 
40
- const startState = streamParser.startState();
40
+ const state = streamParser.startState();
41
41
  let lastPos = stream.pos;
42
42
  while (!stream.eol()) {
43
- const token = streamParser.token(stream, startState);
44
- const segment = stream.current().substring(lastPos, stream.pos);
45
- callback(segment, token);
43
+ stream.start = lastPos;
44
+ let tokenType = streamParser.token(stream, state);
45
+ /**
46
+ * We expect unknown properties (like `unknownProp: unknownPropVal`) to still be
47
+ * formatted correctly. However, `tokenType` for such properties are marked
48
+ * as `error` from CodeMirror side and the internal state of the parser becomes `maybeprop`.
49
+ *
50
+ * So, we handle that specific keyword to be marked as `property` even though it is
51
+ * not a known property. We do this because for our formatting purposes it doesn't matter
52
+ * whether a property is a known CSS property or not.
53
+ */
54
+ if (tokenType === 'error' && state.state === 'maybeprop') {
55
+ tokenType = 'property';
56
+ }
57
+ const segment = stream.current();
58
+ callback(segment, tokenType);
46
59
  lastPos = stream.pos;
47
60
  }
48
61
  }
@@ -34,7 +34,6 @@ import type * as Platform from '../../core/platform/platform.js';
34
34
  export abstract class ContentProvider {
35
35
  abstract contentURL(): Platform.DevToolsPath.UrlString;
36
36
  abstract contentType(): Common.ResourceType.ResourceType;
37
- abstract contentEncoded(): Promise<boolean>;
38
37
  abstract requestContent(): Promise<DeferredContent>;
39
38
  abstract searchInContent(query: string, caseSensitive: boolean, isRegex: boolean): Promise<SearchMatch[]>;
40
39
  }
@@ -39,10 +39,6 @@ export class StaticContentProvider implements ContentProvider {
39
39
  return this.contentTypeInternal;
40
40
  }
41
41
 
42
- contentEncoded(): Promise<boolean> {
43
- return Promise.resolve(false);
44
- }
45
-
46
42
  requestContent(): Promise<DeferredContent> {
47
43
  return this.lazyContent();
48
44
  }
@@ -71,6 +71,7 @@ export class UISourceCode extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
71
71
  private workingCopyGetter: (() => string)|null;
72
72
  private disableEditInternal: boolean;
73
73
  private contentEncodedInternal?: boolean;
74
+ private isKnownThirdPartyInternal: boolean;
74
75
 
75
76
  constructor(project: Project, url: Platform.DevToolsPath.UrlString, contentType: Common.ResourceType.ResourceType) {
76
77
  super();
@@ -108,6 +109,7 @@ export class UISourceCode extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
108
109
  this.workingCopyInternal = null;
109
110
  this.workingCopyGetter = null;
110
111
  this.disableEditInternal = false;
112
+ this.isKnownThirdPartyInternal = false;
111
113
  }
112
114
 
113
115
  requestMetadata(): Promise<UISourceCodeMetadata|null> {
@@ -207,11 +209,6 @@ export class UISourceCode extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
207
209
  return this.contentTypeInternal;
208
210
  }
209
211
 
210
- async contentEncoded(): Promise<boolean> {
211
- await this.requestContent();
212
- return this.contentEncodedInternal || false;
213
- }
214
-
215
212
  project(): Project {
216
213
  return this.projectInternal;
217
214
  }
@@ -401,6 +398,14 @@ export class UISourceCode extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
401
398
  return this.workingCopyInternal !== null || this.workingCopyGetter !== null;
402
399
  }
403
400
 
401
+ isKnownThirdParty(): boolean {
402
+ return this.isKnownThirdPartyInternal;
403
+ }
404
+
405
+ markKnownThirdParty(): void {
406
+ this.isKnownThirdPartyInternal = true;
407
+ }
408
+
404
409
  extension(): string {
405
410
  return Common.ParsedURL.ParsedURL.extractExtension(this.nameInternal);
406
411
  }
@@ -155,7 +155,7 @@ export class StackTrace extends HTMLElement {
155
155
  const expandableRows = [];
156
156
  let hiddenCallFramesCount = 0;
157
157
  for (const item of this.#stackTraceRows) {
158
- if (this.#showHidden || (!item.ignoreListHide && !item.rowCountHide)) {
158
+ if (this.#showHidden || !item.ignoreListHide) {
159
159
  if ('functionName' in item) {
160
160
  expandableRows.push(LitHtml.html`
161
161
  <${StackTraceRow.litTagName} data-stack-trace-row .data=${{
@@ -168,7 +168,7 @@ export class StackTrace extends HTMLElement {
168
168
  `);
169
169
  }
170
170
  }
171
- if (!this.#showHidden && 'functionName' in item && (item.ignoreListHide || item.rowCountHide)) {
171
+ if (!this.#showHidden && 'functionName' in item && item.ignoreListHide) {
172
172
  hiddenCallFramesCount++;
173
173
  }
174
174
  }
@@ -4,44 +4,63 @@
4
4
 
5
5
  import * as i18n from '../../core/i18n/i18n.js';
6
6
 
7
+ import {
8
+ buildStyledPropertyText,
9
+ buildStyledRuleText,
10
+ isFlexContainer,
11
+ isGridContainer,
12
+ isMulticolContainer,
13
+ } from './CSSRuleValidatorHelper.js';
14
+
7
15
  const UIStrings = {
8
16
  /**
9
- *@description Hint prefix for deprecated properties.
17
+ *@description The type of the CSS rule validation message that is shown in the Style panel. "Deprecated property" means that the property in the declaration is deprecated and should not be used.
18
+ */
19
+ deprecatedPropertyHintPrefix: 'Deprecated property',
20
+ /**
21
+ *@description The type of the CSS rule validation message that is shown in the Style panel. "Inactive property" means that a property declaration was valid syntactially but didn't have expected effect.
10
22
  */
11
- deprecatedPropertyHintPrefix: 'Deprecated Property',
23
+ inactivePropertyHintPrefix: 'Inactive property',
12
24
  /**
13
- *@description Hint prefix for rule validation.
25
+ *@description The message that is shown in the Style panel when the user hovers over a property that has not effect due to some other property.
26
+ *@example {flex-wrap: nowrap} REASON_PROPERTY_DECLARATION_CODE
27
+ *@example {align-content} AFFECTED_PROPERTY_DECLARATION_CODE
14
28
  */
15
- ruleValidationHintPrefix: 'Inactive rule',
29
+ ruleViolatedBySameElementRuleReason:
30
+ 'This element has the {REASON_PROPERTY_DECLARATION_CODE} property and therefore, {AFFECTED_PROPERTY_DECLARATION_CODE} has no effect.',
16
31
  /**
17
- *@description Hint for rules that was violated because of same elements rule.
18
- *@example {flex-wrap: nowrap} REASON_RULE_CODE
19
- *@example {align-content} AFFECTED_RULE_CODE
32
+ *@description The message that is shown in the Style panel when the user hovers over a property declaration that has not effect due to some other property.
33
+ *@example {flex-wrap: nowrap} REASON_PROPERTY_DECLARATION_CODE
20
34
  */
21
- ruleViolatedBySameElementRuleReason: 'This element has {REASON_RULE_CODE} rule, therefore {AFFECTED_RULE_CODE} has no effect.',
35
+ ruleViolatedBySameElementRuleFix:
36
+ 'For this property to work, please remove or change the value of {REASON_PROPERTY_DECLARATION_CODE}.',
22
37
  /**
23
- *@description Possible fix for rules that was violated because of same elements rule.
24
- *@example {flex-wrap: nowrap} REASON_RULE_CODE
38
+ *@description The message that is shown in the Style panel when the user hovers over a property declaration that has not effect due to the current property value.
39
+ *@example {display: block} EXISTING_PROPERTY_DECLARATION
40
+ *@example {display: flex} TARGET_PROPERTY_DECLARATION
25
41
  */
26
- ruleViolatedBySameElementRuleFix: 'For this property to work, please remove or change the value of {REASON_RULE_CODE}',
42
+ ruleViolatedBySameElementRuleChangeSuggestion:
43
+ 'For this property to work, please change the {EXISTING_PROPERTY_DECLARATION} rule to {TARGET_PROPERTY_DECLARATION}.',
27
44
  /**
28
- *@description Hint for rules that was violated because of parent element rule.
29
- *@example {display: block} REASON_RULE_CODE
30
- *@example {flex} AFFECTED_RULE_CODE
45
+ *@description The message that is shown in the Style panel when the user hovers over a property declaration that has not effect due to properties of the parent element.
46
+ *@example {display: block} REASON_PROPERTY_DECLARATION_CODE
47
+ *@example {flex} AFFECTED_PROPERTY_DECLARATION_CODE
31
48
  */
32
- ruleViolatedByParentElementRuleReason: 'Parent element has {REASON_RULE_CODE} rule, therefore this elements {AFFECTED_RULE_CODE} has no effect',
49
+ ruleViolatedByParentElementRuleReason:
50
+ 'The parent element has the {REASON_PROPERTY_DECLARATION_CODE} property and therefore, this element\'s property {AFFECTED_PROPERTY_DECLARATION_CODE} has no effect.',
33
51
  /**
34
- *@description Posible fix for rules that was violated because of parent element rule.
52
+ *@description The message that is shown in the Style panel when the user hovers over a property declaration that has not effect due to the properties of the parent element.
35
53
  *@example {display: block} EXISTING_PARENT_ELEMENT_RULE
36
54
  *@example {display: flex} TARGET_PARENT_ELEMENT_RULE
37
55
  */
38
- ruleViolatedByParentElementRuleFix: 'Please change parent elements {EXISTING_PARENT_ELEMENT_RULE} to {TARGET_PARENT_ELEMENT_RULE} to fix this issue.',
39
- };
56
+ ruleViolatedByParentElementRuleFix:
57
+ 'Please change the parent element\'s property declaration from {EXISTING_PARENT_ELEMENT_RULE} to {TARGET_PARENT_ELEMENT_RULE} to fix this issue.',
58
+ };
40
59
  const str_ = i18n.i18n.registerUIStrings('panels/elements/CSSRuleValidator.ts', UIStrings);
41
60
  const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
42
61
 
43
62
  export const enum AuthoringHintType {
44
- RULE_VALIDATION = 'ruleValidation',
63
+ INACTIVE_PROPERTY = 'ruleValidation',
45
64
  DEPRECATED_PROPERTY = 'deprecatedProperty',
46
65
  }
47
66
 
@@ -49,19 +68,20 @@ export class AuthoringHint {
49
68
  readonly #hintType: AuthoringHintType;
50
69
  readonly #hintMessage: string;
51
70
  readonly #possibleFixMessage: string|null;
52
- readonly #learnMore: string|null;
71
+ readonly #learnMoreLink: string|undefined;
53
72
 
54
- constructor(property: string, hintType: AuthoringHintType, hintMessage: string, possibleFixMessage: string|null, showLearnMore: boolean) {
73
+ constructor(
74
+ hintType: AuthoringHintType, hintMessage: string, possibleFixMessage: string|null, learnMoreLink?: string) {
55
75
  this.#hintType = hintType;
56
76
  this.#hintMessage = hintMessage;
57
77
  this.#possibleFixMessage = possibleFixMessage;
58
- this.#learnMore = showLearnMore ? property : null; // TODO: Add Goo.gle short link base url
78
+ this.#learnMoreLink = learnMoreLink;
59
79
  }
60
80
 
61
81
  getHintPrefix(): string {
62
82
  switch (this.#hintType) {
63
- case AuthoringHintType.RULE_VALIDATION:
64
- return i18nString(UIStrings.ruleValidationHintPrefix);
83
+ case AuthoringHintType.INACTIVE_PROPERTY:
84
+ return i18nString(UIStrings.inactivePropertyHintPrefix);
65
85
  case AuthoringHintType.DEPRECATED_PROPERTY:
66
86
  return i18nString(UIStrings.deprecatedPropertyHintPrefix);
67
87
  }
@@ -75,8 +95,8 @@ export class AuthoringHint {
75
95
  return this.#possibleFixMessage;
76
96
  }
77
97
 
78
- getLearnMoreLink(): string|null {
79
- return this.#learnMore;
98
+ getLearnMoreLink(): string|undefined {
99
+ return this.#learnMoreLink;
80
100
  }
81
101
  }
82
102
 
@@ -87,6 +107,9 @@ export abstract class CSSRuleValidator {
87
107
  this.#affectedProperties = affectedProperties;
88
108
  }
89
109
 
110
+ /**
111
+ * If `isRuleValid` returns false, it means there is a hint to be shown. The hint is retrieved by invoking `getAuthoringHint`.
112
+ */
90
113
  abstract isRuleValid(computedStyles: Map<String, String>|null, parentsComputedStyles?: Map<String, String>|null):
91
114
  boolean;
92
115
 
@@ -94,7 +117,9 @@ export abstract class CSSRuleValidator {
94
117
  return this.#affectedProperties;
95
118
  }
96
119
 
97
- abstract getAuthoringHint(propertyName: string, parentComputedStyles: Map<String, String>|null): AuthoringHint;
120
+ abstract getAuthoringHint(
121
+ propertyName: string, computedStyles: Map<String, String>|null,
122
+ parentComputedStyles: Map<String, String>|null): AuthoringHint;
98
123
  }
99
124
 
100
125
  export class AlignContentValidator extends CSSRuleValidator {
@@ -106,28 +131,25 @@ export class AlignContentValidator extends CSSRuleValidator {
106
131
  if (computedStyles === null || computedStyles === undefined) {
107
132
  return true;
108
133
  }
109
- const display = computedStyles.get('display');
110
- if (display !== 'flex' && display !== 'inline-flex') {
134
+ if (!isFlexContainer(computedStyles)) {
111
135
  return true;
112
136
  }
113
137
  return computedStyles.get('flex-wrap') !== 'nowrap';
114
138
  }
115
139
 
116
140
  getAuthoringHint(): AuthoringHint {
117
- const reasonRuleCode = '<code class="unbreakable-text"><span class="property">flex-wrap</span>: nowrap</code>';
118
- const affectedRuleCode = '<code class="unbreakable-text"><span class="property">align-content</span></code>';
141
+ const reasonPropertyDeclaration = buildStyledPropertyText('flex-wrap');
142
+ const affectedPropertyDeclarationCode = buildStyledPropertyText('align-content');
119
143
 
120
144
  return new AuthoringHint(
121
- 'align-content',
122
- AuthoringHintType.RULE_VALIDATION,
123
- i18nString(UIStrings.ruleViolatedBySameElementRuleReason, {
124
- 'REASON_RULE_CODE': reasonRuleCode,
125
- 'AFFECTED_RULE_CODE': affectedRuleCode,
126
- }),
127
- i18nString(UIStrings.ruleViolatedBySameElementRuleFix, {
128
- 'REASON_RULE_CODE': reasonRuleCode,
129
- }),
130
- true,
145
+ AuthoringHintType.INACTIVE_PROPERTY,
146
+ i18nString(UIStrings.ruleViolatedBySameElementRuleReason, {
147
+ 'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
148
+ 'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
149
+ }),
150
+ i18nString(UIStrings.ruleViolatedBySameElementRuleFix, {
151
+ 'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
152
+ }),
131
153
  );
132
154
  }
133
155
  }
@@ -138,40 +160,337 @@ export class FlexItemValidator extends CSSRuleValidator {
138
160
  }
139
161
 
140
162
  isRuleValid(computedStyles: Map<String, String>|null, parentsComputedStyles: Map<String, String>|null): boolean {
141
- if (computedStyles === null || computedStyles === undefined || parentsComputedStyles === null ||
142
- parentsComputedStyles === undefined) {
163
+ if (parentsComputedStyles === null) {
143
164
  return true;
144
165
  }
145
- const parentDisplay = parentsComputedStyles.get('display');
146
- return parentDisplay === 'flex' || parentDisplay === 'inline-flex';
166
+ return isFlexContainer(parentsComputedStyles);
147
167
  }
148
168
 
149
- getAuthoringHint(property: string, parentsComputedStyles: Map<String, String>|null): AuthoringHint {
150
- const reasonRuleCode = '<code class="unbreakable-text"><span class="property">display</span>:' + parentsComputedStyles?.get('display') + '</code>';
151
- const affectedRuleCode = '<code class="unbreakable-text"><span class="property">' + property + '</span></code>';
152
- const targetParentRuleCode = '<code class="unbreakable-text"><span class="property">display</span>: flex</code>';
169
+ getAuthoringHint(
170
+ property: string, computedStyles: Map<String, String>|null,
171
+ parentsComputedStyles: Map<String, String>|null): AuthoringHint {
172
+ const reasonPropertyDeclaration = buildStyledRuleText('display', parentsComputedStyles?.get('display'));
173
+ const affectedPropertyDeclarationCode = buildStyledPropertyText(property);
174
+ const targeParentPropertyDeclaration = buildStyledRuleText('display', 'flex');
153
175
 
154
176
  return new AuthoringHint(
155
- property,
156
- AuthoringHintType.RULE_VALIDATION,
157
- i18nString(UIStrings.ruleViolatedByParentElementRuleReason, {
158
- 'REASON_RULE_CODE': reasonRuleCode,
159
- 'AFFECTED_RULE_CODE': affectedRuleCode,
160
- }),
161
- i18nString(UIStrings.ruleViolatedByParentElementRuleFix, {
162
- 'EXISTING_PARENT_ELEMENT_RULE': reasonRuleCode,
163
- 'TARGET_PARENT_ELEMENT_RULE': targetParentRuleCode,
164
- }),
165
- true,
177
+ AuthoringHintType.INACTIVE_PROPERTY,
178
+ i18nString(UIStrings.ruleViolatedByParentElementRuleReason, {
179
+ 'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
180
+ 'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
181
+ }),
182
+ i18nString(UIStrings.ruleViolatedByParentElementRuleFix, {
183
+ 'EXISTING_PARENT_ELEMENT_RULE': reasonPropertyDeclaration,
184
+ 'TARGET_PARENT_ELEMENT_RULE': targeParentPropertyDeclaration,
185
+ }),
166
186
  );
167
187
  }
168
188
  }
169
189
 
170
- const setupCSSRulesValidators = (): Map<String, CSSRuleValidator[]> => {
171
- const validators = [new AlignContentValidator(), new FlexItemValidator()];
190
+ export class FlexContainerValidator extends CSSRuleValidator {
191
+ constructor() {
192
+ super(['flex-direction', 'flex-flow', 'flex-wrap', 'justify-content']);
193
+ }
194
+
195
+ isRuleValid(computedStyles: Map<String, String>|null): boolean {
196
+ if (computedStyles === null) {
197
+ return true;
198
+ }
199
+ return isFlexContainer(computedStyles);
200
+ }
201
+
202
+ getAuthoringHint(property: string, computedStyles: Map<String, String>|null): AuthoringHint {
203
+ const reasonPropertyDeclaration = buildStyledRuleText('display', computedStyles?.get('display'));
204
+ const targetRuleCode = buildStyledRuleText('display', 'flex');
205
+ const affectedPropertyDeclarationCode = buildStyledPropertyText(property);
206
+
207
+ return new AuthoringHint(
208
+ AuthoringHintType.INACTIVE_PROPERTY,
209
+ i18nString(UIStrings.ruleViolatedBySameElementRuleReason, {
210
+ 'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
211
+ 'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
212
+ }),
213
+ i18nString(UIStrings.ruleViolatedBySameElementRuleChangeSuggestion, {
214
+ 'EXISTING_PROPERTY_DECLARATION': reasonPropertyDeclaration,
215
+ 'TARGET_PROPERTY_DECLARATION': targetRuleCode,
216
+ }),
217
+ );
218
+ }
219
+ }
220
+
221
+ export class GridContainerValidator extends CSSRuleValidator {
222
+ constructor() {
223
+ super([
224
+ 'grid',
225
+ 'grid-auto-columns',
226
+ 'grid-auto-flow',
227
+ 'grid-auto-rows',
228
+ 'grid-template',
229
+ 'grid-template-areas',
230
+ 'grid-template-columns',
231
+ 'grid-template-rows',
232
+ ]);
233
+ }
234
+
235
+ isRuleValid(computedStyles: Map<String, String>|null): boolean {
236
+ if (computedStyles === null) {
237
+ return true;
238
+ }
239
+ return isGridContainer(computedStyles);
240
+ }
241
+
242
+ getAuthoringHint(property: string, computedStyles: Map<String, String>|null): AuthoringHint {
243
+ const reasonPropertyDeclaration = buildStyledRuleText('display', computedStyles?.get('display'));
244
+ const targetRuleCode = buildStyledRuleText('display', 'grid');
245
+ const affectedPropertyDeclarationCode = buildStyledPropertyText(property);
246
+
247
+ return new AuthoringHint(
248
+ AuthoringHintType.INACTIVE_PROPERTY,
249
+ i18nString(UIStrings.ruleViolatedBySameElementRuleReason, {
250
+ 'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
251
+ 'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
252
+ }),
253
+ i18nString(UIStrings.ruleViolatedBySameElementRuleChangeSuggestion, {
254
+ 'EXISTING_PROPERTY_DECLARATION': reasonPropertyDeclaration,
255
+ 'TARGET_PROPERTY_DECLARATION': targetRuleCode,
256
+ }),
257
+ );
258
+ }
259
+ }
260
+
261
+ export class GridItemValidator extends CSSRuleValidator {
262
+ constructor() {
263
+ super([
264
+ 'grid-area',
265
+ 'grid-column',
266
+ 'grid-row',
267
+ 'grid-row-end',
268
+ 'grid-row-start',
269
+ ]);
270
+ }
271
+
272
+ isRuleValid(computedStyles: Map<String, String>|null, parentComputedStyles: Map<String, String>|null): boolean {
273
+ if (parentComputedStyles === null) {
274
+ return true;
275
+ }
276
+ return isGridContainer(parentComputedStyles);
277
+ }
278
+
279
+ getAuthoringHint(
280
+ property: string, computedStyles: Map<String, String>|null,
281
+ parentComputedStyles: Map<String, String>|null): AuthoringHint {
282
+ const reasonPropertyDeclaration = buildStyledRuleText('display', parentComputedStyles?.get('display'));
283
+ const targeParentPropertyDeclaration = buildStyledRuleText('display', 'grid');
284
+ const affectedPropertyDeclarationCode = buildStyledPropertyText(property);
285
+
286
+ return new AuthoringHint(
287
+ AuthoringHintType.INACTIVE_PROPERTY,
288
+ i18nString(UIStrings.ruleViolatedByParentElementRuleReason, {
289
+ 'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
290
+ 'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
291
+ }),
292
+ i18nString(UIStrings.ruleViolatedByParentElementRuleFix, {
293
+ 'EXISTING_PARENT_ELEMENT_RULE': reasonPropertyDeclaration,
294
+ 'TARGET_PARENT_ELEMENT_RULE': targeParentPropertyDeclaration,
295
+ }),
296
+ );
297
+ }
298
+ }
299
+
300
+ export class FlexGridValidator extends CSSRuleValidator {
301
+ constructor() {
302
+ super([
303
+ 'order',
304
+ 'align-content',
305
+ 'align-items',
306
+ 'align-self',
307
+ ]);
308
+ }
172
309
 
310
+ isRuleValid(computedStyles: Map<String, String>|null): boolean {
311
+ if (computedStyles === null) {
312
+ return true;
313
+ }
314
+ return isFlexContainer(computedStyles) || isGridContainer(computedStyles);
315
+ }
316
+
317
+ getAuthoringHint(property: string, computedStyles: Map<String, String>|null): AuthoringHint {
318
+ const reasonPropertyDeclaration = buildStyledRuleText('display', computedStyles?.get('display'));
319
+ const affectedPropertyDeclarationCode = buildStyledPropertyText(property);
320
+
321
+ return new AuthoringHint(
322
+ AuthoringHintType.INACTIVE_PROPERTY,
323
+ i18nString(UIStrings.ruleViolatedBySameElementRuleReason, {
324
+ 'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
325
+ 'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
326
+ }),
327
+ i18nString(UIStrings.ruleViolatedBySameElementRuleFix, {
328
+ 'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
329
+ }),
330
+ );
331
+ }
332
+ }
333
+
334
+ export class MulticolFlexGridValidator extends CSSRuleValidator {
335
+ constructor() {
336
+ super([
337
+ 'gap',
338
+ 'column-gap',
339
+ 'row-gap',
340
+ 'grid-gap',
341
+ 'grid-column-gap',
342
+ 'grid-column-end',
343
+ 'grid-row-gap',
344
+ ]);
345
+ }
346
+
347
+ isRuleValid(computedStyles: Map<String, String>|null): boolean {
348
+ if (computedStyles === null) {
349
+ return true;
350
+ }
351
+ return isMulticolContainer(computedStyles) || isFlexContainer(computedStyles) || isGridContainer(computedStyles);
352
+ }
353
+
354
+ getAuthoringHint(property: string, computedStyles: Map<String, String>|null): AuthoringHint {
355
+ const reasonPropertyDeclaration = buildStyledRuleText('display', computedStyles?.get('display'));
356
+ const affectedPropertyDeclarationCode = buildStyledPropertyText(property);
357
+
358
+ return new AuthoringHint(
359
+ AuthoringHintType.INACTIVE_PROPERTY,
360
+ i18nString(UIStrings.ruleViolatedBySameElementRuleReason, {
361
+ 'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
362
+ 'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
363
+ }),
364
+ i18nString(UIStrings.ruleViolatedBySameElementRuleFix, {
365
+ 'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
366
+ }),
367
+ );
368
+ }
369
+ }
370
+
371
+ export class PaddingValidator extends CSSRuleValidator {
372
+ constructor() {
373
+ super([
374
+ 'padding',
375
+ 'padding-top',
376
+ 'padding-right',
377
+ 'padding-bottom',
378
+ 'padding-left',
379
+ ]);
380
+ }
381
+
382
+ isRuleValid(computedStyles: Map<String, String>|null): boolean {
383
+ const display = computedStyles?.get('display');
384
+ if (display === null || display === undefined) {
385
+ return true;
386
+ }
387
+ return !['table-row-group', 'table-header-group', 'table-footer-group', 'table-row', 'table-column-group',
388
+ 'table-column']
389
+ .includes(display as string);
390
+ }
391
+
392
+ getAuthoringHint(property: string, computedStyles: Map<String, String>|null): AuthoringHint {
393
+ const reasonPropertyDeclaration = buildStyledRuleText('display', computedStyles?.get('display'));
394
+ const affectedPropertyDeclarationCode = buildStyledPropertyText(property);
395
+
396
+ return new AuthoringHint(
397
+ AuthoringHintType.INACTIVE_PROPERTY,
398
+ i18nString(UIStrings.ruleViolatedBySameElementRuleReason, {
399
+ 'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
400
+ 'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
401
+ }),
402
+ i18nString(UIStrings.ruleViolatedBySameElementRuleFix, {
403
+ 'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
404
+ }),
405
+ );
406
+ }
407
+ }
408
+
409
+ export class PositionValidator extends CSSRuleValidator {
410
+ constructor() {
411
+ super([
412
+ 'top',
413
+ 'right',
414
+ 'bottom',
415
+ 'left',
416
+ ]);
417
+ }
418
+
419
+ isRuleValid(computedStyles: Map<String, String>|null): boolean {
420
+ const position = computedStyles?.get('position');
421
+ if (position === null || position === undefined) {
422
+ return true;
423
+ }
424
+ return position !== 'static';
425
+ }
426
+
427
+ getAuthoringHint(property: string, computedStyles: Map<String, String>|null): AuthoringHint {
428
+ const reasonPropertyDeclaration = buildStyledRuleText('position', computedStyles?.get('position'));
429
+ const affectedPropertyDeclarationCode = buildStyledPropertyText(property);
430
+
431
+ return new AuthoringHint(
432
+ AuthoringHintType.INACTIVE_PROPERTY,
433
+ i18nString(UIStrings.ruleViolatedBySameElementRuleReason, {
434
+ 'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
435
+ 'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
436
+ }),
437
+ i18nString(UIStrings.ruleViolatedBySameElementRuleFix, {
438
+ 'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
439
+ }),
440
+ );
441
+ }
442
+ }
443
+
444
+ export class ZIndexValidator extends CSSRuleValidator {
445
+ constructor() {
446
+ super([
447
+ 'z-index',
448
+ ]);
449
+ }
450
+
451
+ isRuleValid(computedStyles: Map<String, String>|null, parentComputedStyles: Map<String, String>|null): boolean {
452
+ const position = computedStyles?.get('position');
453
+ if (position === null || position === undefined) {
454
+ return true;
455
+ }
456
+ return ['absolute', 'relative', 'fixed', 'sticky'].includes(position as string) ||
457
+ isFlexContainer(parentComputedStyles);
458
+ }
459
+
460
+ getAuthoringHint(property: string, computedStyles: Map<String, String>|null): AuthoringHint {
461
+ const reasonPropertyDeclaration = buildStyledRuleText('position', computedStyles?.get('position'));
462
+ const affectedPropertyDeclarationCode = buildStyledPropertyText(property);
463
+
464
+ return new AuthoringHint(
465
+ AuthoringHintType.INACTIVE_PROPERTY,
466
+ i18nString(UIStrings.ruleViolatedBySameElementRuleReason, {
467
+ 'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
468
+ 'AFFECTED_PROPERTY_DECLARATION_CODE': affectedPropertyDeclarationCode,
469
+ }),
470
+ i18nString(UIStrings.ruleViolatedBySameElementRuleFix, {
471
+ 'REASON_PROPERTY_DECLARATION_CODE': reasonPropertyDeclaration,
472
+ }),
473
+ );
474
+ }
475
+ }
476
+
477
+ const CSS_RULE_VALIDATORS = [
478
+ AlignContentValidator,
479
+ FlexItemValidator,
480
+ FlexContainerValidator,
481
+ GridContainerValidator,
482
+ GridItemValidator,
483
+ FlexGridValidator,
484
+ MulticolFlexGridValidator,
485
+ PaddingValidator,
486
+ PositionValidator,
487
+ ZIndexValidator,
488
+ ];
489
+
490
+ const setupCSSRulesValidators = (): Map<String, CSSRuleValidator[]> => {
173
491
  const validatorsMap = new Map<String, CSSRuleValidator[]>();
174
- for (const validator of validators) {
492
+ for (const validatorClass of CSS_RULE_VALIDATORS) {
493
+ const validator = new validatorClass();
175
494
  const affectedProperties = validator.getAffectedProperties();
176
495
 
177
496
  for (const affectedProperty of affectedProperties) {