Custom ESLint rules to enforce new ThemedComponent selector convention

The following cases are covered:
- ThemedComponent wrapper selectors must not start with ds-themed-
- Base component selectors must start with ds-base-
- Themed component selectors must start with ds-themed-
- The ThemedComponent wrapper must always be used in HTML
- The ThemedComponent wrapper must be used in TypeScript _where appropriate_:
  - Required
    - Explicit usages (e.g. modal instantiation, routing modules, ...)
    - By.css selector queries (in order to align with the HTML rule)
  - Unchecked
    - Non-routing modules (to ensure the components can be declared)
    - ViewChild hooks (since they need to attach to the underlying component)

All rules work with --fix to automatically migrate to the new convention
This covers most of the codebase, but minor manual adjustment are needed afterwards
This commit is contained in:
Yury Bondarenko
2024-03-14 10:00:10 +01:00
parent 41eccbbfe1
commit 3937be13f2
35 changed files with 1352 additions and 34 deletions

View File

@@ -0,0 +1,56 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
import {
DISALLOWED_THEME_SELECTORS,
fixSelectors,
} from '../../util/theme-support';
export default {
meta: {
type: 'problem',
fixable: 'code',
schema: [],
messages: {
mustUseThemedWrapperSelector: 'Themeable components should be used via their ThemedComponent wrapper\'s selector',
}
},
create(context: any) {
return {
[`Element$1[name = /^${DISALLOWED_THEME_SELECTORS}/]`](node: any) {
context.report({
messageId: 'mustUseThemedWrapperSelector',
node,
fix(fixer: any) {
const oldSelector = node.name;
const newSelector = fixSelectors(oldSelector);
const openTagRange = [
node.startSourceSpan.start.offset + 1,
node.startSourceSpan.start.offset + 1 + oldSelector.length
];
const ops = [
fixer.replaceTextRange(openTagRange, newSelector),
];
// make sure we don't mangle self-closing tags
if (node.startSourceSpan.end.offset !== node.endSourceSpan.end.offset) {
const closeTagRange = [
node.endSourceSpan.start.offset + 2,
node.endSourceSpan.end.offset - 1
];
ops.push(fixer.replaceTextRange(closeTagRange, newSelector));
}
return ops;
}
});
},
};
}
};