-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(sdk/skyux-eslint): add
no-deprecated-classnames
rule (#2953)
- Loading branch information
1 parent
7f34a3f
commit 5ca8de6
Showing
11 changed files
with
218 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
apps/code-examples/src/app/code-examples/forms/checkbox/basic/demo.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
apps/code-examples/src/app/code-examples/forms/checkbox/help-key/demo.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
apps/code-examples/src/app/code-examples/forms/checkbox/icon-group/demo.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
libs/sdk/skyux-eslint/docs/rules/template/no-deprecated-classnames.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# `skyux-eslint-template/no-deprecated-classnames` | ||
|
||
Prevents usage of deprecated CSS classnames in HTML templates. | ||
|
||
- Type: problem | ||
|
||
<br> | ||
|
||
## Rule Options | ||
|
||
The rule does not have any configuration options. | ||
|
||
<br> | ||
|
||
## Usage Examples | ||
|
||
#### Default Config | ||
|
||
```json | ||
{ | ||
"rules": { | ||
"skyux-eslint-template/no-deprecated-classnames": ["error"] | ||
} | ||
} | ||
``` | ||
|
||
#### ❌ Invalid Code | ||
|
||
```html | ||
<div class="sky-margin-inline-compact"></div> | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
61 changes: 61 additions & 0 deletions
61
libs/sdk/skyux-eslint/src/rules/template/no-deprecated-classnames.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { convertAnnotatedSourceToFailureCase } from '@angular-eslint/test-utils'; | ||
|
||
import { createTemplateRuleTester } from '../testing/create-template-rule-tester'; | ||
|
||
import { RULE_NAME, messageId, rule } from './no-deprecated-classnames'; | ||
|
||
const ruleTester = createTemplateRuleTester(); | ||
|
||
ruleTester.run(RULE_NAME, rule, { | ||
valid: [``], | ||
invalid: [ | ||
convertAnnotatedSourceToFailureCase({ | ||
description: 'should fail with one classname', | ||
annotatedSource: ` | ||
<div class="sky-margin-inline-compact"></div> | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
`, | ||
annotatedOutput: ` | ||
<div class="sky-margin-inline-xs"></div> | ||
~ | ||
`, | ||
messageId, | ||
data: { | ||
deprecated: 'sky-margin-inline-compact', | ||
replacement: 'sky-margin-inline-xs', | ||
}, | ||
}), | ||
convertAnnotatedSourceToFailureCase({ | ||
description: 'should fail with multiple classnames', | ||
annotatedSource: ` | ||
<div class="sky-margin-inline-compact sky-field-label"></div> | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
`, | ||
annotatedOutput: ` | ||
<div class="sky-margin-inline-xs sky-font-data-label"></div> | ||
~ | ||
`, | ||
messageId, | ||
data: { | ||
deprecated: 'sky-margin-inline-compact, sky-field-label', | ||
replacement: 'sky-margin-inline-xs, sky-font-data-label', | ||
}, | ||
}), | ||
convertAnnotatedSourceToFailureCase({ | ||
description: 'should ignore other classnames', | ||
annotatedSource: ` | ||
<div class="sky-margin-inline-compact foobar sky-field-label"></div> | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
`, | ||
annotatedOutput: ` | ||
<div class="sky-margin-inline-xs foobar sky-font-data-label"></div> | ||
~ | ||
`, | ||
messageId, | ||
data: { | ||
deprecated: 'sky-margin-inline-compact, sky-field-label', | ||
replacement: 'sky-margin-inline-xs, sky-font-data-label', | ||
}, | ||
}), | ||
], | ||
}); |
110 changes: 110 additions & 0 deletions
110
libs/sdk/skyux-eslint/src/rules/template/no-deprecated-classnames.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import { TmplAstTextAttribute } from '@angular-eslint/bundled-angular-compiler'; | ||
import { getTemplateParserServices } from '@angular-eslint/utils'; | ||
import { RuleFix } from '@typescript-eslint/utils/dist/ts-eslint'; | ||
|
||
import { createESLintTemplateRule } from '../utils/create-eslint-template-rule'; | ||
|
||
export const RULE_NAME = 'no-deprecated-classnames'; | ||
export const messageId = 'noDeprecatedClassnames'; | ||
|
||
/** | ||
* A map of deprecated classnames to their replacements. | ||
*/ | ||
export const DEPRECATED_CLASSNAMES: Record<string, string> = { | ||
'sky-margin-inline-compact': 'sky-margin-inline-xs', | ||
'sky-margin-inline-default': 'sky-margin-inline-sm', | ||
'sky-margin-stacked-compact': 'sky-margin-stacked-xs', | ||
'sky-margin-stacked-default': 'sky-margin-stacked-lg', | ||
'sky-margin-stacked-separate': 'sky-margin-stacked-xl', | ||
'sky-padding-even-default': 'sky-padding-even-md', | ||
'sky-padding-even-large': 'sky-padding-even-xl', | ||
'sky-page-heading': 'sky-font-heading-1', | ||
'sky-section-heading': 'sky-font-heading-2', | ||
'sky-subsection-heading': 'sky-font-heading-3', | ||
'sky-headline': 'sky-font-display-3', | ||
'sky-emphasized': 'sky-font-emphasized', | ||
'sky-deemphasized': 'sky-font-deemphasized', | ||
'sky-field-label': 'sky-font-data-label', | ||
}; | ||
|
||
function getDeprecatedClasses( | ||
existingClasses: string[], | ||
): Record<string, string> { | ||
const found: Record<string, string> = {}; | ||
|
||
for (const existingClassname of existingClasses) { | ||
const replacement = DEPRECATED_CLASSNAMES[existingClassname]; | ||
|
||
if (replacement) { | ||
found[existingClassname] = DEPRECATED_CLASSNAMES[existingClassname]; | ||
} | ||
} | ||
|
||
return found; | ||
} | ||
|
||
export const rule = createESLintTemplateRule({ | ||
create(context) { | ||
const parserServices = getTemplateParserServices(context); | ||
|
||
return { | ||
[`Element$1 > :matches(TextAttribute)[name="class"]`]( | ||
attr: TmplAstTextAttribute, | ||
): void { | ||
const existing = attr.value.split(' '); | ||
const found = getDeprecatedClasses(existing); | ||
|
||
const deprecatedClasses = Object.keys(found); | ||
const replacementClasses = Object.values(found); | ||
|
||
if (deprecatedClasses.length > 0) { | ||
for (const deprecatedClassname of deprecatedClasses) { | ||
const index = existing.indexOf(deprecatedClassname); | ||
|
||
if (index > -1) { | ||
existing[index] = found[deprecatedClassname]; | ||
} | ||
} | ||
|
||
context.report({ | ||
loc: parserServices.convertNodeSourceSpanToLoc(attr.sourceSpan), | ||
messageId, | ||
data: { | ||
deprecated: deprecatedClasses.join(', '), | ||
replacement: replacementClasses.join(', '), | ||
}, | ||
fix: () => { | ||
const fixers: RuleFix[] = []; | ||
|
||
if (attr.valueSpan) { | ||
fixers.push({ | ||
range: [ | ||
attr.valueSpan.start.offset, | ||
attr.valueSpan.end.offset, | ||
], | ||
text: existing.join(' '), | ||
}); | ||
} | ||
|
||
return fixers; | ||
}, | ||
}); | ||
} | ||
}, | ||
}; | ||
}, | ||
defaultOptions: [], | ||
meta: { | ||
docs: { | ||
description: 'Avoid using deprecated CSS classes.', | ||
}, | ||
messages: { | ||
[messageId]: | ||
'The CSS classes ({{deprecated}}) are deprecated. Use ({{replacement}}) instead.', | ||
}, | ||
schema: [], | ||
type: 'problem', | ||
fixable: 'code', | ||
}, | ||
name: RULE_NAME, | ||
}); |