-
Notifications
You must be signed in to change notification settings - Fork 498
/
Copy pathenforce-custom-element-definitions-location.ts
95 lines (83 loc) · 3.1 KB
/
enforce-custom-element-definitions-location.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import path from 'node:path';
import {createRule} from './utils/ruleCreator.ts';
export default createRule<[{rootFrontendDirectory: string}], 'definitionInWrongFolder'>({
name: 'enforce-custom-element-definitions-location',
meta: {
type: 'problem',
docs: {
description: 'ensure that custom element definitions are in the correct folders.',
category: 'Possible Errors',
},
fixable: 'code',
messages: {
definitionInWrongFolder: 'A custom element definition was found in a folder that ' +
'should not contain element definitions. If you want to define a custom element, ' +
'either place it in `ui/components/` or in a `components` sub-folder of a panel. ' +
'E.g. `panels/elements/components/`.',
},
schema: [
{
type: 'object',
properties: {
rootFrontendDirectory: {
type: 'string',
},
},
additionalProperties: false,
},
],
},
defaultOptions: [{rootFrontendDirectory: ''}],
create: function(context) {
const filename = context.filename ?? context.getFilename();
const classDefiningFileName = path.resolve(filename);
let frontEndDirectory = '';
if (context.options[0]?.rootFrontendDirectory) {
frontEndDirectory = context.options[0].rootFrontendDirectory;
}
if (!frontEndDirectory) {
throw new Error(
'rootFrontEndDirectory must be provided to custom_elements_definitions_location.',
);
}
const PANELS_DIRECTORY = path.join(frontEndDirectory, 'panels');
const ALLOWED_CUSTOM_ELEMENT_LOCATIONS = new Set([
path.join(frontEndDirectory, 'ui', 'components'),
// These should be moved to `ui/components` at some point
path.join(frontEndDirectory, 'ui', 'legacy'),
// path.join(frontEndDirectory, 'ui', 'legacy', 'components', 'inline_editor'),
// path.join(frontEndDirectory, 'ui', 'legacy', 'components', 'perf_ui', 'PieChart.ts'),
// path.join(frontEndDirectory, 'ui', 'legacy', 'XElement.ts'),
]);
return {
ClassDeclaration(node) {
if (node.superClass?.type !== 'Identifier' || node.superClass?.name !== 'HTMLElement') {
return;
}
for (const allowedLocation of ALLOWED_CUSTOM_ELEMENT_LOCATIONS) {
if (classDefiningFileName.startsWith(allowedLocation)) {
return;
}
}
if (classDefiningFileName.startsWith(PANELS_DIRECTORY)) {
const filePathWithPanelName = classDefiningFileName.substring(
PANELS_DIRECTORY.length + 1,
);
const filePathWithoutPanelName = filePathWithPanelName.substring(
filePathWithPanelName.indexOf(path.sep) + 1,
);
if (filePathWithoutPanelName.includes(`components${path.sep}`)) {
return;
}
}
context.report({
node,
messageId: 'definitionInWrongFolder',
});
},
};
},
});