Skip to content

Commit ff94562

Browse files
Lightning00BladeDevtools-frontend LUCI CQ
authored andcommitted
[eslint] Enforce custom elements naming
Enforce a custom elements prefix `devtool-` to signify that the we are the creators of the implementation. Bug: none Change-Id: Ie4c4dedbd2fe6c63b1002e4bfcac3deb59a1e2a4 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/7095724 Reviewed-by: Benedikt Meurer <[email protected]> Commit-Queue: Nikolay Vitkov <[email protected]>
1 parent e47cf44 commit ff94562

File tree

10 files changed

+298
-149
lines changed

10 files changed

+298
-149
lines changed

eslint.config.mjs

Lines changed: 151 additions & 149 deletions
Large diffs are not rendered by default.

front_end/panels/emulation/components/DeviceSizeInputElement.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ export class SizeInputElement extends HTMLElement {
121121
}
122122
}
123123

124+
// eslint-disable-next-line @devtools/enforce-custom-element-prefix
124125
customElements.define('device-mode-emulation-size-input', SizeInputElement);
125126

126127
declare global {

front_end/ui/components/icon_button/IconButton.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export class IconButton extends HTMLElement {
9393
}
9494
}
9595

96+
// eslint-disable-next-line @devtools/enforce-custom-element-prefix
9697
customElements.define('icon-button', IconButton);
9798

9899
declare global {

front_end/ui/components/settings/SettingCheckbox.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ export class SettingCheckbox extends HTMLElement {
176176
}
177177
}
178178

179+
// eslint-disable-next-line @devtools/enforce-custom-element-prefix
179180
customElements.define('setting-checkbox', SettingCheckbox);
180181

181182
declare global {

front_end/ui/legacy/UIUtils.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,6 +1480,7 @@ export class DevToolsIconLabel extends HTMLElement {
14801480
}
14811481
}
14821482

1483+
// eslint-disable-next-line @devtools/enforce-custom-element-prefix
14831484
customElements.define('dt-icon-label', DevToolsIconLabel);
14841485

14851486
export class DevToolsSmallBubble extends HTMLElement {
@@ -1498,6 +1499,7 @@ export class DevToolsSmallBubble extends HTMLElement {
14981499
}
14991500
}
15001501

1502+
// eslint-disable-next-line @devtools/enforce-custom-element-prefix
15011503
customElements.define('dt-small-bubble', DevToolsSmallBubble);
15021504

15031505
export class DevToolsCloseButton extends HTMLElement {
@@ -1536,6 +1538,7 @@ export class DevToolsCloseButton extends HTMLElement {
15361538
}
15371539
}
15381540

1541+
// eslint-disable-next-line @devtools/enforce-custom-element-prefix
15391542
customElements.define('dt-close-button', DevToolsCloseButton);
15401543

15411544
export function bindInput(

front_end/ui/legacy/XLink.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,4 +153,5 @@ export class ContextMenuProvider implements Provider<Node> {
153153
}
154154
}
155155

156+
// eslint-disable-next-line @devtools/enforce-custom-element-prefix
156157
customElements.define('x-link', XLink);

front_end/ui/legacy/components/inline_editor/Swatches.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export class CSSShadowSwatch extends HTMLElement {
3838
}
3939
}
4040

41+
// eslint-disable-next-line @devtools/enforce-custom-element-prefix
4142
customElements.define('css-shadow-swatch', CSSShadowSwatch);
4243

4344
declare global {

front_end/ui/legacy/components/perf_ui/BrickBreaker.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,4 +602,5 @@ declare global {
602602
}
603603
}
604604

605+
// eslint-disable-next-line @devtools/enforce-custom-element-prefix
605606
customElements.define('brick-breaker', BrickBreaker);
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright 2025 The Chromium Authors
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import type {TSESTree} from '@typescript-eslint/types';
6+
7+
import {createRule} from './utils/ruleCreator.ts';
8+
9+
function getTextValue(node: TSESTree.Node): string|undefined {
10+
if (node.type === 'Literal') {
11+
return node.value?.toString();
12+
}
13+
if (node.type === 'TemplateLiteral') {
14+
if (node.quasis.length === 0) {
15+
return;
16+
}
17+
return node.quasis[0].value.cooked;
18+
}
19+
return;
20+
}
21+
22+
export default createRule({
23+
name: 'enforce-custom-element-prefix',
24+
meta: {
25+
type: 'problem',
26+
docs: {
27+
description: 'Enforce that all customElements.define() calls use a "devtools-" prefix for the tag name.',
28+
category: 'Possible Errors',
29+
},
30+
messages: {
31+
onlyStatic: 'Custom element tag name should be called with static string.',
32+
missingPrefix: 'Custom element tag name \'{{tagName}}\' must be prefixed with \'devtools-\'.',
33+
},
34+
schema: [],
35+
},
36+
defaultOptions: [],
37+
create: function(context) {
38+
return {
39+
CallExpression(node: TSESTree.CallExpression) {
40+
const callee = node.callee;
41+
42+
// customElements.define(<string>, <class>);
43+
if (callee.type !== 'MemberExpression' || callee.object.type !== 'Identifier' ||
44+
callee.object.name !== 'customElements' || callee.property.type !== 'Identifier' ||
45+
callee.property.name !== 'define') {
46+
return;
47+
}
48+
49+
const firstArg = node.arguments[0];
50+
if (!firstArg) {
51+
return;
52+
}
53+
54+
const tagName = getTextValue(firstArg);
55+
56+
if (typeof tagName !== 'string') {
57+
context.report({
58+
node: firstArg,
59+
messageId: 'onlyStatic',
60+
});
61+
return;
62+
}
63+
64+
if (!tagName.startsWith('devtools-')) {
65+
context.report({
66+
node: firstArg,
67+
messageId: 'missingPrefix',
68+
data: {
69+
tagName,
70+
},
71+
});
72+
}
73+
},
74+
};
75+
},
76+
});
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2025 The Chromium Authors
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import rule from '../lib/enforce-custom-element-prefix.ts';
6+
7+
import {RuleTester} from './utils/RuleTester.ts';
8+
9+
new RuleTester().run('enforce-custom-element-prefix', rule, {
10+
valid: [
11+
{
12+
code: `customElements.define('devtools-my-element', class extends HTMLElement {})`,
13+
},
14+
{
15+
code: 'customElements.define(`devtools-another-element`, class extends HTMLElement {})',
16+
},
17+
{
18+
code: `MyElements.define('my-element', class extends HTMLElement {})`,
19+
}
20+
],
21+
invalid: [
22+
{
23+
code: `const myTag = 'my-element'; customElements.define(myTag, class extends HTMLElement {})`,
24+
errors: [{
25+
messageId: 'onlyStatic',
26+
}],
27+
},
28+
{
29+
code: `customElements.define('my-element', class extends HTMLElement {})`,
30+
errors: [{
31+
messageId: 'missingPrefix',
32+
data: {tagName: 'my-element'},
33+
}],
34+
},
35+
{
36+
code: 'customElements.define(`bad-element`, class extends HTMLElement {})',
37+
errors: [
38+
{messageId: 'missingPrefix', data: {tagName: 'bad-element'}},
39+
],
40+
},
41+
{
42+
code: `customElements.define('', class extends HTMLElement {})`,
43+
errors: [{messageId: 'missingPrefix', data: {tagName: ''}}],
44+
},
45+
{
46+
code: `customElements.define('chrome-my-element', class extends HTMLElement {})`,
47+
errors: [
48+
{messageId: 'missingPrefix', data: {tagName: 'chrome-my-element'}},
49+
],
50+
},
51+
{
52+
code: `customElements.define('DEVTOOLS-my-element', class extends HTMLElement {})`,
53+
errors: [
54+
{messageId: 'missingPrefix', data: {tagName: 'DEVTOOLS-my-element'}},
55+
],
56+
},
57+
{
58+
code: `customElements.define('devtoolselement', class extends HTMLElement {})`,
59+
errors: [{messageId: 'missingPrefix', data: {tagName: 'devtoolselement'}}],
60+
},
61+
],
62+
});

0 commit comments

Comments
 (0)