Skip to content

Commit 1e5cadb

Browse files
authored
Merge pull request #2453 from cardstack/eslint-plugin-boxel
introduce eslint-plugin-boxel package, with template-missing-invokable rule
2 parents cfc25e2 + 9bd6685 commit 1e5cadb

File tree

45 files changed

+6115
-1732
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+6115
-1732
lines changed

.github/workflows/ci-lint.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ jobs:
119119
if: always()
120120
run: pnpm run lint
121121
working-directory: packages/vscode-boxel-tools
122+
- name: Lint ESLint Plugin
123+
if: always()
124+
run: pnpm run lint
125+
working-directory: packages/eslint-plugin-boxel
122126
- name: Lint AI Bot
123127
if: always()
124128
run: pnpm run lint

eslint/missing-invokables-config.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/* eslint-disable no-undef */
2+
'use strict';
3+
4+
module.exports = {
5+
invokables: {
6+
fn: ['fn', '@ember/helper'],
7+
on: ['on', '@ember/modifier'],
8+
and: ['and', '@cardstack/boxel-ui/helpers'],
9+
bool: ['bool', '@cardstack/boxel-ui/helpers'],
10+
eq: ['eq', '@cardstack/boxel-ui/helpers'],
11+
gt: ['gt', '@cardstack/boxel-ui/helpers'],
12+
lt: ['lt', '@cardstack/boxel-ui/helpers'],
13+
not: ['not', '@cardstack/boxel-ui/helpers'],
14+
or: ['or', '@cardstack/boxel-ui/helpers'],
15+
add: ['add', '@cardstack/boxel-ui/helpers'],
16+
subtract: ['subtract', '@cardstack/boxel-ui/helpers'],
17+
},
18+
};

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@
5757
"@glint/environment-ember-loose": "1.3.0",
5858
"@glint/environment-ember-template-imports": "1.3.0",
5959
"@playwright/test": "^1.48.0",
60-
"@typescript-eslint/eslint-plugin": "^5.17.0",
61-
"@typescript-eslint/parser": "^5.17.0",
60+
"@typescript-eslint/eslint-plugin": "^7.16.1",
61+
"@typescript-eslint/parser": "^7.16.1",
6262
"ember-cli-htmlbars": "^6.3.0",
6363
"ember-resources": "^6.5.1",
6464
"ember-source": "~5.4.0",

packages/boxel-icons/.eslintrc.cjs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use strict';
22

3+
const MISSING_INVOKABLES_CONFIG = require('../../eslint/missing-invokables-config');
4+
35
module.exports = {
46
root: true,
57
parser: '@typescript-eslint/parser',
@@ -35,6 +37,40 @@ module.exports = {
3537
],
3638
},
3739
overrides: [
40+
{
41+
files: ['**/*.gts'],
42+
parser: 'ember-eslint-parser',
43+
parserOptions: {
44+
ecmaVersion: 'latest',
45+
sourceType: 'module',
46+
requireConfigFile: false,
47+
babelOptions: {
48+
plugins: [
49+
[
50+
'@babel/plugin-proposal-decorators',
51+
{ decoratorsBeforeExport: true },
52+
],
53+
],
54+
},
55+
warnOnUnsupportedTypeScriptVersion: false,
56+
},
57+
plugins: ['ember', '@cardstack/boxel'],
58+
extends: [
59+
'eslint:recommended',
60+
'plugin:@typescript-eslint/recommended',
61+
'plugin:ember/recommended',
62+
'plugin:ember/recommended-gts',
63+
'plugin:prettier/recommended',
64+
'plugin:qunit-dom/recommended',
65+
'plugin:@cardstack/boxel/recommended',
66+
],
67+
rules: {
68+
'@cardstack/boxel/template-missing-invokable': [
69+
'error',
70+
{ invokables: MISSING_INVOKABLES_CONFIG.invokables },
71+
],
72+
},
73+
},
3874
// node files
3975
{
4076
files: [

packages/boxel-icons/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"@babel/plugin-transform-class-static-block": "^7.22.11",
4646
"@babel/plugin-transform-typescript": "^7.22.15",
4747
"@babel/runtime": "^7.22.11",
48+
"@cardstack/eslint-plugin-boxel": "workspace:*",
4849
"@lucide/lab": "^0.1.2",
4950
"@tabler/icons": "^3.19.0",
5051
"@embroider/addon-dev": "^5.0.0",
@@ -61,7 +62,7 @@
6162
"ember-template-lint-plugin-prettier": "^5.0.0",
6263
"eslint": "^8.56.0",
6364
"eslint-config-prettier": "^8.6.0",
64-
"eslint-plugin-ember": "^11.4.2",
65+
"eslint-plugin-ember": "^12.5.0",
6566
"eslint-plugin-n": "^15.6.0",
6667
"eslint-plugin-prettier": "^5.0.0",
6768
"http-server": "^14.1.1",

packages/boxel-motion/addon/.eslintrc.cjs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,52 @@ module.exports = {
4343
],
4444
},
4545
overrides: [
46+
{
47+
files: ['**/*.gts'],
48+
parser: 'ember-eslint-parser',
49+
parserOptions: {
50+
ecmaVersion: 'latest',
51+
sourceType: 'module',
52+
requireConfigFile: false,
53+
babelOptions: {
54+
plugins: [
55+
[
56+
'@babel/plugin-proposal-decorators',
57+
{ decoratorsBeforeExport: true },
58+
],
59+
],
60+
},
61+
warnOnUnsupportedTypeScriptVersion: false,
62+
},
63+
plugins: ['ember'],
64+
extends: [
65+
'eslint:recommended',
66+
'plugin:@typescript-eslint/recommended',
67+
'plugin:ember/recommended',
68+
'plugin:ember/recommended-gts',
69+
'plugin:prettier/recommended',
70+
'plugin:qunit-dom/recommended',
71+
],
72+
rules: {
73+
'@typescript-eslint/no-empty-function': 'off',
74+
'@typescript-eslint/no-unused-vars': [
75+
'error',
76+
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
77+
],
78+
'prefer-const': 'off',
79+
'@typescript-eslint/no-explicit-any': 'off',
80+
'@typescript-eslint/ban-types': 'off',
81+
'@typescript-eslint/ban-ts-comment': 'off',
82+
'@typescript-eslint/explicit-module-boundary-types': 'off',
83+
'@typescript-eslint/no-this-alias': 'off',
84+
'@typescript-eslint/no-non-null-assertion': 'off',
85+
'no-undef': 'off',
86+
'ember/template-no-let-reference': 'off',
87+
'ember/no-tracked-properties-from-args': 'off',
88+
'ember/no-runloop': 'off',
89+
'node/no-deprecated-api': 'off',
90+
},
91+
},
4692
// node files
4793
{
4894
files: [

packages/boxel-motion/addon/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
"ember-template-lint-plugin-prettier": "^5.0.0",
7777
"eslint": "^8.56.0",
7878
"eslint-config-prettier": "^8.6.0",
79-
"eslint-plugin-ember": "^11.4.2",
79+
"eslint-plugin-ember": "^12.5.0",
8080
"eslint-plugin-n": "^15.6.0",
8181
"eslint-plugin-prettier": "^5.0.0",
8282
"eslint-plugin-simple-import-sort": "^8.0.0",

packages/boxel-motion/addon/src/services/animations.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export default class AnimationsService extends Service {
4949
this.animationParticipantManager.clearSnapshots();
5050
this.animationParticipantManager.snapshotBeforeRender();
5151

52+
// eslint-disable-next-line ember/no-runloop
5253
scheduleOnce('afterRender', this, this.maybeTransition);
5354
}
5455
}

packages/boxel-motion/addon/src/utils/scheduling.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ export function afterRender() {
2020
let promise = new Promise((resolve) => {
2121
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
2222
// @ts-ignore
23+
// eslint-disable-next-line ember/no-runloop
2324
ticket = schedule('afterRender', resolve);
2425
});
2526
registerCancellation(promise, () => {
27+
// eslint-disable-next-line ember/no-runloop
2628
cancel(ticket);
2729
});
2830
return promise;

packages/boxel-motion/test-app/package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"@cardstack/boxel-motion": "workspace:*",
3131
"@ember/optional-features": "^2.0.0",
3232
"@ember/string": "^3.1.1",
33-
"@ember/test-helpers": "^3.2.0",
33+
"@ember/test-helpers": "^3.3.1",
3434
"@embroider/compat": "^3.5.5",
3535
"@embroider/core": "^3.4.14",
3636
"@embroider/macros": "^1.16.5",
@@ -46,8 +46,8 @@
4646
"@types/htmlbars-inline-precompile": "^3.0.3",
4747
"@types/qunit": "^2.19.10",
4848
"@types/rsvp": "^4.0.9",
49-
"@typescript-eslint/eslint-plugin": "^5.48.1",
50-
"@typescript-eslint/parser": "^5.48.1",
49+
"@typescript-eslint/eslint-plugin": "^7.16.1",
50+
"@typescript-eslint/parser": "^7.16.1",
5151
"broccoli-asset-rev": "^3.0.0",
5252
"concurrently": "^8.2.2",
5353
"ember-a11y-testing": "^6.1.1",
@@ -81,9 +81,9 @@
8181
"ember-template-imports": "^4.1.1",
8282
"ember-template-lint": "^5.11.2",
8383
"ember-try": "^2.0.0",
84-
"eslint": "^8.52.0",
84+
"eslint": "^8.56.0",
8585
"eslint-config-prettier": "^9.0.0",
86-
"eslint-plugin-ember": "^11.11.1",
86+
"eslint-plugin-ember": "^12.5.0",
8787
"eslint-plugin-n": "^16.2.0",
8888
"eslint-plugin-prettier": "^5.0.1",
8989
"eslint-plugin-qunit": "^8.0.1",
@@ -96,7 +96,7 @@
9696
"qunit-dom": "^2.0.0",
9797
"tracked-built-ins": "^3.3.0",
9898
"typescript": "~5.1.6",
99-
"webpack": "^5.89.0"
99+
"webpack": "^5.99.6"
100100
},
101101
"engines": {
102102
"node": ">= 18"

packages/boxel-ui/addon/.eslintrc.cjs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
'use strict';
22

3+
const MISSING_INVOKABLES_CONFIG = require('../../../eslint/missing-invokables-config');
4+
35
module.exports = {
46
root: true,
57
parser: '@typescript-eslint/parser',
@@ -43,6 +45,57 @@ module.exports = {
4345
],
4446
},
4547
overrides: [
48+
{
49+
files: ['**/*.gts'],
50+
parser: 'ember-eslint-parser',
51+
parserOptions: {
52+
ecmaVersion: 'latest',
53+
sourceType: 'module',
54+
requireConfigFile: false,
55+
babelOptions: {
56+
plugins: [
57+
[
58+
'@babel/plugin-proposal-decorators',
59+
{ decoratorsBeforeExport: true },
60+
],
61+
],
62+
},
63+
warnOnUnsupportedTypeScriptVersion: false,
64+
},
65+
plugins: ['ember', '@cardstack/boxel'],
66+
extends: [
67+
'eslint:recommended',
68+
'plugin:@typescript-eslint/recommended',
69+
'plugin:ember/recommended',
70+
'plugin:ember/recommended-gts',
71+
'plugin:prettier/recommended',
72+
'plugin:qunit-dom/recommended',
73+
'plugin:@cardstack/boxel/recommended',
74+
],
75+
rules: {
76+
'@typescript-eslint/no-empty-function': 'off',
77+
'@typescript-eslint/no-unused-vars': [
78+
'error',
79+
{ argsIgnorePattern: '^_', varsIgnorePattern: '^_' },
80+
],
81+
'prefer-const': 'off',
82+
'@typescript-eslint/no-explicit-any': 'off',
83+
'@typescript-eslint/ban-types': 'off',
84+
'@typescript-eslint/ban-ts-comment': 'off',
85+
'@typescript-eslint/explicit-module-boundary-types': 'off',
86+
'@typescript-eslint/no-this-alias': 'off',
87+
'@typescript-eslint/no-non-null-assertion': 'off',
88+
'no-undef': 'off',
89+
'ember/template-no-let-reference': 'off',
90+
'ember/no-tracked-properties-from-args': 'off',
91+
'ember/no-runloop': 'off',
92+
'node/no-deprecated-api': 'off',
93+
'@cardstack/boxel/template-missing-invokable': [
94+
'error',
95+
{ invokables: MISSING_INVOKABLES_CONFIG.invokables },
96+
],
97+
},
98+
},
4699
// node files
47100
{
48101
files: [

packages/boxel-ui/addon/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
"@babel/plugin-transform-class-static-block": "^7.22.11",
7676
"@babel/plugin-transform-typescript": "^7.22.15",
7777
"@babel/runtime": "^7.22.11",
78+
"@cardstack/eslint-plugin-boxel": "workspace:*",
7879
"@embroider/addon-dev": "^5.0.0",
7980
"@embroider/macros": "^1.16.5",
8081
"@rollup/plugin-babel": "^6.0.4",
@@ -90,7 +91,7 @@
9091
"ember-template-lint-plugin-prettier": "^5.0.0",
9192
"eslint": "^8.56.0",
9293
"eslint-config-prettier": "^8.6.0",
93-
"eslint-plugin-ember": "^11.4.2",
94+
"eslint-plugin-ember": "^12.5.0",
9495
"eslint-plugin-n": "^15.6.0",
9596
"eslint-plugin-prettier": "^5.0.0",
9697
"glimmer-scoped-css": "^0.6.0",

packages/boxel-ui/addon/src/components/basic-fitted/index.gts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ interface Signature {
1616
Element: HTMLDivElement;
1717
}
1818

19+
// eslint-disable-next-line ember/no-empty-glimmer-component-classes
1920
export default class BasicFitted extends Component<Signature> {
2021
<template>
2122
<div class='fitted-template' ...attributes>

packages/boxel-ui/addon/src/components/card-content-container/usage.gts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ interface Signature {
77
Element: HTMLElement;
88
}
99

10+
// eslint-disable-next-line ember/no-empty-glimmer-component-classes
1011
export default class CardContentContainerUsage extends Component<Signature> {
1112
<template>
1213
<FreestyleUsage @name='CardContentContainer'>

packages/boxel-ui/addon/src/components/circle-spinner/index.gts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ interface Signature {
66
Element: SVGElement;
77
}
88

9+
// eslint-disable-next-line ember/no-empty-glimmer-component-classes
910
export default class CircleSpinner extends Component<Signature> {
1011
<template>
1112
<IconCircle class='circle-spinner' ...attributes />

packages/boxel-ui/addon/src/components/grid-container/usage.gts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ interface Signature {
77
Element: HTMLElement;
88
}
99

10+
// eslint-disable-next-line ember/no-empty-glimmer-component-classes
1011
export default class GridContainerUsage extends Component<Signature> {
1112
<template>
1213
<FreestyleUsage @name='GridContainer'>

packages/boxel-ui/addon/src/components/multi-select/usage.gts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ interface CheckBoxArgs {
4040
Element: Element;
4141
}
4242

43+
// eslint-disable-next-line ember/no-empty-glimmer-component-classes
4344
class CheckboxIndicator extends Component<CheckBoxArgs> {
4445
<template>
4546
<div class='checkbox-indicator'>
@@ -83,6 +84,7 @@ interface AssigneePillArgs {
8384
}
8485

8586
//Custom component for rendering dropdown items with enhanced design and functionality
87+
// eslint-disable-next-line ember/no-empty-glimmer-component-classes
8688
class AssigneePill extends Component<AssigneePillArgs> {
8789
<template>
8890
<span class='assignee-pill'>

packages/boxel-ui/addon/src/components/phone-input/index.gts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ export interface SelectedItemSignature {
159159
Element: HTMLDivElement;
160160
}
161161

162+
// eslint-disable-next-line ember/no-empty-glimmer-component-classes
162163
class PhoneSelectedItem extends Component<SelectedItemSignature> {
163164
<template>
164165
<div>

packages/boxel-ui/addon/src/components/radio-input/index.gts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export default class RadioInput extends Component<Signature> {
7070
white-space: nowrap;
7171
}
7272
73-
/* Div container inside the fieldset component. Use \`display: contents\` to move
73+
/* Div container inside the fieldset component. Use display: contents to move
7474
these styles up when that css property is more widely available. */
7575
.boxel-radio-fieldset__container {
7676
display: flex;

packages/boxel-ui/addon/src/components/select/trigger.gts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ export class BoxelTriggerWrapper extends Component<TriggerSignature> {
7777
</template>
7878
}
7979

80+
// eslint-disable-next-line ember/no-empty-glimmer-component-classes
8081
export class BoxelSelectDefaultTrigger extends Component<TriggerSignature> {
8182
<template>
8283
<BoxelTriggerWrapper @placeholder={{@placeholder}} @select={{@select}}>

packages/boxel-ui/addon/src/components/switch/index.gts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ interface SwitchArgs {
1414
onChange: () => void;
1515
}
1616

17+
// eslint-disable-next-line ember/no-empty-glimmer-component-classes
1718
export default class Switch extends Component<SwitchSiganture> {
1819
<template>
1920
<label

0 commit comments

Comments
 (0)