@starterlib/eslint-config 0.10.13 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,6 +24,8 @@ export default configurationDuSocle({ prefixe: 'ct', racine: import.meta.dirname
24
24
 
25
25
  `role: 'hote'` pour la coquille : un remote n'a pas le droit de FOURNIR le noyau, le routeur ou le
26
26
  client HTTP (seul l'hote les fournit), l'hote si. `ignores` ajoute des chemins a ne pas lire.
27
+ `variantesReservees` (P08-11) : les variantes que l'application reserve a des emplacements (regle
28
+ `variantes-reservees` du greffon ; Aplomb reserve `stButton variante="danger"` a l'arret d'urgence).
27
29
 
28
30
  `.stylelintrc.json` :
29
31
 
@@ -48,14 +50,20 @@ Chaque regle repond a une ligne du plan SPA §4 ou de l'ADR 0029.
48
50
  - Donnees : aucun tri local (`sort`, `toSorted`) dans un fichier qui importe les tableaux du socle
49
51
  (`@starterlib/ui/listes`) : il ne trierait que la page chargee ; le tri passe a l'API (lot 224).
50
52
  - Gabarits (`@starterlib/eslint-plugin`) : aucun element interactif nu, aucun texte litteral, aucun
51
- pipe de locale d'Angular ; code : un titre par route, aucun toast d'erreur, aucun texte libre dans
53
+ pipe de locale d'Angular, aucun style local (`no-style-literal`, P08-11), aucune variante reservee
54
+ hors de ses emplacements ; code : un titre par route, aucun toast d'erreur, aucun texte libre dans
52
55
  l'adresse.
53
- - Feuilles (stylelint) : aucune couleur ecrite (un derive de jeton est admis), aucun `px` non nul sur
54
- un espacement, une police ou un rayon, aucun `z-index` en nombre, ni `order` ni sens inverse.
56
+ - Feuilles (stylelint) : aucune couleur ecrite (un derive de jeton est admis ; `lab()`, `lch()`,
57
+ `oklab()`, `oklch()` et `color()` comptent), aucun `px` non nul sur un espacement, une police ou un
58
+ rayon, aucun `z-index` en nombre, ni `order` ni sens inverse ; P08-11 : un rayon, une ombre et une
59
+ police viennent d'un jeton `--st-*`, et aucune declaration `--st-*` hors des reglages de niveau 3.
60
+ Le depot du socle, qui FAIT le design, n'etend que les regles communes (`REGLES_COMMUNES`).
55
61
 
56
62
  Les essais (`*.spec.ts`) pilotent le DOM et montent des routes et des composants hotes : `window`,
57
63
  `document`, les routes sans titre et les gabarits en ligne y sont admis. L'hote de developpement d'un
58
64
  remote (`src/hote-dev`, jamais livre) ne parle qu'aux developpeurs : textes litteraux admis.
59
65
 
60
66
  Une exception s'ecrit sur place, avec sa raison : `// eslint-disable-next-line <regle> -- <raison>`,
61
- `// stylelint-disable-next-line <regle> -- <raison>`.
67
+ `// stylelint-disable-next-line <regle> -- <raison>` (stylelint refuse une exception sans raison).
68
+ Une exception aux regles de STYLE (P08-11) est aussi DATEE et se journalise dans le CHANGELOG de
69
+ l'application : `-- AAAA-MM-JJ : <raison>` ; l'etape `lint` de `starter-web verify` le verifie.
package/index.mjs CHANGED
@@ -158,7 +158,9 @@ const FOURNI_PAR_L_HOTE = [
158
158
  * `import.meta.dirname` de son `eslint.config.mjs` (le projet TypeScript) ; `role` : `remote` (par
159
159
  * defaut) ou `hote` ; `ignores` : des chemins de plus a ne pas lire ; `nomDesElements` : le nom
160
160
  * ENREGISTRE sous lequel la SPA definit ses custom elements (`<nom>-*`, lot 299, registre des custom
161
- * elements du socle frontal), absent tant qu'elle n'en definit aucun.
161
+ * elements du socle frontal), absent tant qu'elle n'en definit aucun ; `variantesReservees` : les
162
+ * variantes que l'application reserve a certains emplacements (P08-11, regle `variantes-reservees` ;
163
+ * Aplomb : `stButton variante="danger"` a l'arret d'urgence seul, DEC-105).
162
164
  */
163
165
  export function configurationDuSocle({
164
166
  prefixe,
@@ -166,6 +168,7 @@ export function configurationDuSocle({
166
168
  role = 'remote',
167
169
  ignores = [],
168
170
  nomDesElements,
171
+ variantesReservees = [],
169
172
  } = {}) {
170
173
  if (typeof prefixe !== 'string' || !PREFIXE.test(prefixe) || prefixe === 'st') {
171
174
  throw new Error(
@@ -292,6 +295,11 @@ export function configurationDuSocle({
292
295
  'socle/no-raw-interactive': 'error',
293
296
  'socle/no-literal-text': 'error',
294
297
  'socle/no-angular-locale-pipes': 'error',
298
+ // Lot 281 : l'affichage se decide par une permission (*stPermission), jamais par un role.
299
+ 'socle/no-role-comparison': 'error',
300
+ // P08-11 : seul le socle fait le design ; les variantes reservees par l'application.
301
+ 'socle/no-style-literal': 'error',
302
+ 'socle/variantes-reservees': ['error', { reservees: variantesReservees }],
295
303
  },
296
304
  },
297
305
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@starterlib/eslint-config",
3
- "version": "0.10.13",
3
+ "version": "0.11.0",
4
4
  "description": "Configuration ESLint d'une SPA du socle frontal starter, parametree par son prefixe, et configuration stylelint de ses feuilles. Remplace les eslint.config.mjs recopies.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "peerDependencies": {
20
20
  "@eslint/js": "^10.0.1",
21
- "@starterlib/eslint-plugin": "^0.10.0",
21
+ "@starterlib/eslint-plugin": "^0.11.0",
22
22
  "angular-eslint": "^22.5.0",
23
23
  "eslint": "^10.10.0",
24
24
  "typescript-eslint": "^8.70.0"
package/stylelint.mjs CHANGED
@@ -8,9 +8,10 @@
8
8
  * { "extends": ["@starterlib/eslint-config/stylelint"] }
9
9
  * ```
10
10
  *
11
- * - aucune couleur ecrite (hexadecimal, nom, `rgb()`, `hsl()`...) : un jeton `--st-*`, qui suit le
12
- * theme. Une couleur DERIVEE d'un jeton (`rgb(from var(--st-couleur-primaire) r g b / 10%)`) en est
13
- * un usage, pas une invention : elle est admise ;
11
+ * - aucune couleur ecrite (hexadecimal, nom, `rgb()`, `hsl()`, `hwb()`, `lab()`, `lch()`,
12
+ * `oklab()`, `oklch()`, `color()`) : un jeton `--st-*`, qui suit le theme. Une couleur DERIVEE d'un
13
+ * jeton (`rgb(from var(--st-couleur-primaire) r g b / 10%)`) en est un usage, pas une invention :
14
+ * elle est admise ;
14
15
  * - aucun `px` NON NUL sur un espacement, une police ou un rayon : les jetons de rythme, de
15
16
  * typographie et de forme, qui suivent la densite et le zoom du texte. Un `0px` de repli
16
17
  * (`var(--st-hauteur-entete, 0px)`, `env(safe-area-inset-bottom, 0px)` dans un `calc()`, ou un `0`
@@ -19,32 +20,104 @@
19
20
  * - ni `order` ni sens inverse (`row-reverse`, `column-reverse`) : l'ordre du DOM est l'ordre visuel,
20
21
  * celui de la lecture et de la tabulation.
21
22
  *
22
- * Une exception s'ecrit sur place, avec sa raison :
23
- * `// stylelint-disable-next-line <regle> -- <raison>`.
23
+ * P08-11 (seul le socle fait le design, DEC-100 d'Aplomb), pour une SPA seulement (le depot du
24
+ * socle, qui fait le design, n'etend que `REGLES_COMMUNES`) : un rayon, une ombre (`box-shadow`,
25
+ * `text-shadow`, `drop-shadow()`) et une police (`font`, `font-family`) viennent d'un jeton
26
+ * `--st-*` (ou `0`, `none`, un mot-cle CSS) ; aucune declaration `--st-*` hors des reglages de
27
+ * niveau 3 (`REGLAGES_DE_NIVEAU_3`). Les gabarits sont gardes par la regle `no-style-literal` de
28
+ * `@starterlib/eslint-plugin`, avec les memes refus.
29
+ *
30
+ * Une exception s'ecrit sur place, nommee et DATEE, et se journalise dans le CHANGELOG de
31
+ * l'application : `// stylelint-disable-next-line <regle> -- AAAA-MM-JJ : <raison>`.
32
+ */
33
+
34
+ /**
35
+ * Les reglages de niveau 3 qu'une SPA peut poser : la liste du README des jetons (« Niveau 3 ») et le
36
+ * reglage d'affichage `--st-prefixe-de-ton`. La MEME que `REGLAGES_DE_NIVEAU_3` de
37
+ * `@starterlib/eslint-plugin`, recopiee : cette configuration se lit aussi dans le depot du socle, ou
38
+ * le greffon ne se resout pas. Une garde du depot confronte les trois.
24
39
  */
40
+ export const REGLAGES_DE_NIVEAU_3 = Object.freeze([
41
+ 'anim-chargement',
42
+ 'anim-respiration',
43
+ 'calendrier-jour-taille',
44
+ 'carte-rayon',
45
+ 'champ-largeur-libelle',
46
+ 'commande-hauteur',
47
+ 'commande-rayon',
48
+ 'coquille-largeur-navigation',
49
+ 'liste-hauteur-max',
50
+ 'prefixe-de-ton',
51
+ 'separateur-marge',
52
+ 'surface-rayon',
53
+ 'tableau-cellule-bloc',
54
+ 'tableau-cellule-ligne',
55
+ 'tableau-largeur-case',
56
+ ]);
25
57
 
26
58
  /** Une fonction de couleur qui n'est pas derivee d'un jeton du socle. */
27
- const COULEUR_ECRITE = '/(^|[^-\\w])(rgba?|hsla?|hwb)\\((?!\\s*from\\s+var\\(--st-)/';
59
+ const COULEUR_ECRITE =
60
+ '/(^|[^-\\w])(rgba?|hsla?|hwb|lab|lch|oklab|oklch|color)\\((?!\\s*from\\s+var\\(--st-)/';
28
61
 
29
62
  /** Une mesure en pixels non nulle, negative comprise. */
30
63
  const PIXELS_NON_NULS = '/(^|[^\\w.])-?(?!0px\\b)(\\d*\\.)?\\d+px\\b/';
31
64
 
32
- export default {
33
- rules: {
34
- 'color-no-hex': true,
35
- 'color-named': 'never',
36
- 'declaration-property-value-disallowed-list': {
37
- '/.*/': [COULEUR_ECRITE],
38
- '/^(margin|padding|gap|row-gap|column-gap|inset)/': [PIXELS_NON_NULS],
39
- '/^(font-size|line-height|letter-spacing|word-spacing)$/': [PIXELS_NON_NULS],
40
- '/^border(-(start|end)-(start|end)|-(top|bottom)-(left|right))?-radius$/': [PIXELS_NON_NULS],
41
- 'flex-direction': ['/reverse/'],
42
- 'flex-flow': ['/reverse/'],
43
- },
44
- 'declaration-property-value-allowed-list': {
45
- 'z-index': ['/^var\\(--st-/', '/^calc\\(var\\(--st-/', 'auto', '0'],
46
- },
47
- 'property-disallowed-list': ['order'],
65
+ /** Une ombre portee par un filtre, ecrite plutot que tiree d'un jeton. */
66
+ const OMBRE_DE_FILTRE = '/drop-shadow\\((?!\\s*var\\(--st-)/';
67
+
68
+ /** Une valeur tiree d'un jeton du socle, ou un mot-cle CSS. */
69
+ const DE_JETON = [
70
+ '/^var\\(\\s*--st-/',
71
+ '/^calc\\(.*var\\(\\s*--st-/',
72
+ 'inherit',
73
+ 'initial',
74
+ 'unset',
75
+ 'revert',
76
+ ];
77
+
78
+ /** Un rayon, quel que soit le coin. */
79
+ const RAYON = '/^border(-(start|end)-(start|end)|-(top|bottom)-(left|right))?-radius$/';
80
+
81
+ /** Une declaration `--st-*` qui n'est pas un reglage de niveau 3. */
82
+ const JETON_REDEFINI = `/^--st-(?!(?:${REGLAGES_DE_NIVEAU_3.join('|')})$)/`;
83
+
84
+ /** Les regles du socle ET des SPA : couleurs, pixels, plans, ordre du DOM. */
85
+ export const REGLES_COMMUNES = Object.freeze({
86
+ 'color-no-hex': true,
87
+ 'color-named': 'never',
88
+ 'declaration-property-value-disallowed-list': {
89
+ '/.*/': [COULEUR_ECRITE],
90
+ '/^(margin|padding|gap|row-gap|column-gap|inset)/': [PIXELS_NON_NULS],
91
+ '/^(font-size|line-height|letter-spacing|word-spacing)$/': [PIXELS_NON_NULS],
92
+ [RAYON]: [PIXELS_NON_NULS],
93
+ 'flex-direction': ['/reverse/'],
94
+ 'flex-flow': ['/reverse/'],
95
+ },
96
+ 'declaration-property-value-allowed-list': {
97
+ 'z-index': ['/^var\\(--st-/', '/^calc\\(var\\(--st-/', 'auto', '0'],
98
+ },
99
+ 'property-disallowed-list': ['order'],
100
+ });
101
+
102
+ /** P08-11 : ce qu'une SPA n'ecrit jamais, la ou le socle fait le design. */
103
+ const REGLES_DES_SPA = {
104
+ ...REGLES_COMMUNES,
105
+ 'declaration-property-value-disallowed-list': {
106
+ ...REGLES_COMMUNES['declaration-property-value-disallowed-list'],
107
+ '/^(filter|backdrop-filter)$/': [OMBRE_DE_FILTRE],
48
108
  },
109
+ 'declaration-property-value-allowed-list': {
110
+ ...REGLES_COMMUNES['declaration-property-value-allowed-list'],
111
+ [RAYON]: [...DE_JETON, '0'],
112
+ '/^(box-shadow|text-shadow)$/': [...DE_JETON, 'none'],
113
+ '/^(font|font-family)$/': DE_JETON,
114
+ },
115
+ 'property-disallowed-list': [...REGLES_COMMUNES['property-disallowed-list'], JETON_REDEFINI],
116
+ };
117
+
118
+ export default {
119
+ rules: REGLES_DES_SPA,
120
+ // Une exception sans raison ne se lit pas a la revue.
121
+ reportDescriptionlessDisables: true,
49
122
  overrides: [{ files: ['**/*.scss'], customSyntax: 'postcss-scss' }],
50
123
  };