eslint-plugin-sfmc 4.1.0 → 4.1.1

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
@@ -163,14 +163,14 @@ The MSO rules are **auto-included** in the HTML-embedded configs: `embedded`, `s
163
163
 
164
164
  | Rule (`mso/*`) | Default (embedded/strict) | Description |
165
165
  | ---------------------------------- | ------------------------- | ------------------------------------------------------------- |
166
- | `mso/valid-mso-condition` | `error` | Validate the `[if …]` expression syntax of MSO comments |
167
- | `mso/matching-mso-endif` | `error` | Require every MSO opener to have a matching `<![endif]>` |
168
- | `mso/matching-mso-endif-type` | `warn` | Require the endif comment style to match its opener |
169
- | `mso/no-unknown-mso-property` | `warn` | Flag unknown `mso-*` CSS properties |
170
- | `mso/vml-requires-namespace` | `warn` | Require the `v:` VML namespace declaration when VML is used |
171
- | `mso/no-unknown-vml-tag` | `warn` | Flag unknown `v:*` VML tags |
172
- | `mso/no-unknown-vml-attribute` | `warn` | Flag unknown attributes on VML tags |
173
- | `mso/table-presentation-role` | `warn` | Require `role="presentation"` on layout tables |
166
+ | [`mso/valid-mso-condition`](https://github.com/JoernBerkefeld/eslint-plugin-mso-email/blob/main/docs/rules/valid-mso-condition.md) | `error` | Validate the `[if …]` expression syntax of MSO comments |
167
+ | [`mso/matching-mso-endif`](https://github.com/JoernBerkefeld/eslint-plugin-mso-email/blob/main/docs/rules/matching-mso-endif.md) | `error` | Require every MSO opener to have a matching `<![endif]>` |
168
+ | [`mso/matching-mso-endif-type`](https://github.com/JoernBerkefeld/eslint-plugin-mso-email/blob/main/docs/rules/matching-mso-endif-type.md) | `warn` | Require the endif comment style to match its opener |
169
+ | [`mso/no-unknown-mso-property`](https://github.com/JoernBerkefeld/eslint-plugin-mso-email/blob/main/docs/rules/no-unknown-mso-property.md) | `warn` | Flag unknown `mso-*` CSS properties |
170
+ | [`mso/vml-requires-namespace`](https://github.com/JoernBerkefeld/eslint-plugin-mso-email/blob/main/docs/rules/vml-requires-namespace.md) | `warn` | Require the `v:` VML namespace declaration when VML is used |
171
+ | [`mso/no-unknown-vml-tag`](https://github.com/JoernBerkefeld/eslint-plugin-mso-email/blob/main/docs/rules/no-unknown-vml-tag.md) | `warn` | Flag unknown `v:*` VML tags |
172
+ | [`mso/no-unknown-vml-attribute`](https://github.com/JoernBerkefeld/eslint-plugin-mso-email/blob/main/docs/rules/no-unknown-vml-attribute.md) | `warn` | Flag unknown attributes on VML tags |
173
+ | [`mso/table-presentation-role`](https://github.com/JoernBerkefeld/eslint-plugin-mso-email/blob/main/docs/rules/table-presentation-role.md) | `warn` | Require `role="presentation"` on layout tables |
174
174
 
175
175
  Severities above are the same in `embedded`, `strict`, `embedded-next`, and `strict-next` (MSO markup is engine-agnostic — it behaves identically for Engagement and Next). For MSO rule details and options, see the [`eslint-plugin-mso-email` docs](https://github.com/JoernBerkefeld/eslint-plugin-mso-email).
176
176
 
@@ -190,8 +190,7 @@ export default [
190
190
  eslintPluginUnicorn.configs.recommended, // you opt in — registers the `unicorn` plugin
191
191
  ...sfmc.configs.recommended,
192
192
  ...sfmc.configs['unicorn-ssjs'], // OPTIONAL: off the 46 SFMC-incompatible unicorn rules for SSJS
193
- // For SSJS embedded in HTML (<script runat="server">), also add:
194
- // ...sfmc.configs['unicorn-ssjs-embedded'],
193
+ ...sfmc.configs['unicorn-ssjs-embedded'], // OPTIONAL: same override for SSJS embedded in HTML (<script runat="server">)
195
194
  ];
196
195
  ```
197
196
 
@@ -9,11 +9,100 @@
9
9
  - **ECMAScript built-ins support** — <https://ssjs.guide/ecmascript-builtins/>
10
10
  - **Engine limitations** — <https://ssjs.guide/engine-limitations/>
11
11
 
12
- Of unicorn's **300** recommended rules (v71.1.0), **254** are safe to keep on for SSJS and **46** should be turned off. `eslint-plugin-sfmc` ships an **optional** override config (`unicorn-ssjs` / `unicorn-ssjs-embedded`) that turns off exactly those 46 for SSJS files. `eslint-plugin-sfmc` does **not** depend on or load unicorn — the override only takes effect when you have loaded unicorn yourself. See [Section 3](#section-3--how-to-apply).
12
+ Of unicorn's **300** recommended rules (v71.1.0), **254** are safe to keep on for SSJS and **46** should be turned off. `eslint-plugin-sfmc` ships an **optional** override config (`unicorn-ssjs` / `unicorn-ssjs-embedded`) that turns off exactly those 46 for SSJS files. `eslint-plugin-sfmc` does **not** depend on or load unicorn — the override only takes effect when you have loaded unicorn yourself. See [Section 1](#section-1--how-to-apply).
13
13
 
14
14
  ---
15
15
 
16
- ## Section 1 — Rules OK as-is (254)
16
+ ## Section 1 — How to apply
17
+
18
+ The override is **optional** and **SSJS-scoped**. `eslint-plugin-sfmc` never loads unicorn; the override is a plain rules object that only resolves when you have loaded your own unicorn config **earlier** in the flat-config array (that config registers the `unicorn` plugin). Spread the sfmc override **after** it:
19
+
20
+ ```js
21
+ import sfmc from 'eslint-plugin-sfmc';
22
+ import eslintPluginUnicorn from 'eslint-plugin-unicorn';
23
+
24
+ export default [
25
+ eslintPluginUnicorn.configs.recommended, // you opt in — registers the `unicorn` plugin
26
+ ...sfmc.configs.recommended,
27
+ ...sfmc.configs['unicorn-ssjs'], // OPTIONAL: off the 46 SFMC-incompatible unicorn rules for SSJS
28
+ ...sfmc.configs['unicorn-ssjs-embedded'], // OPTIONAL: same override for SSJS embedded in HTML (<script runat="server">)
29
+ ];
30
+ ```
31
+
32
+ | Config | Applies to |
33
+ |---|---|
34
+ | `unicorn-ssjs` | `**/*.ssjs` |
35
+ | `unicorn-ssjs-embedded` | `**/*.html/*.js` (SSJS extracted from `<script runat="server">`) |
36
+
37
+ If you don't use unicorn, omit these configs entirely — nothing else in `eslint-plugin-sfmc` references them.
38
+
39
+ ---
40
+
41
+ ## Section 2 — Rules to override for SSJS (46)
42
+
43
+ These 46 recommended rules either **autofix code to a missing built-in**, **forbid a documented SFMC workaround**, or **enforce ES-module / async / ES6-only syntax** the engine cannot run. The override config sets each to `'off'` for SSJS. All 46 are confirmed `recommended` in unicorn v71.1.0.
44
+
45
+ ### Group A — autofix to a missing built-in / forbid a SFMC workaround (41)
46
+
47
+ | Rule | Why it breaks SSJS | SFMC evidence |
48
+ |---|---|---|
49
+ | [`prefer-includes`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-includes.md) | Pushes `Array/String#includes()` — missing in SSJS | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
50
+ | [`prefer-string-starts-ends-with`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-starts-ends-with.md) | Pushes `String#startsWith/endsWith` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
51
+ | [`prefer-string-trim-start-end`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-trim-start-end.md) | Pushes `trimStart/trimEnd` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
52
+ | [`prefer-string-slice`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-slice.md) | Forbids `substring`, the SFMC-safe choice | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
53
+ | [`prefer-string-replace-all`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-replace-all.md) | Pushes `String#replaceAll` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
54
+ | [`prefer-string-repeat`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-repeat.md) | Pushes `String#repeat` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
55
+ | [`prefer-string-pad-start-end`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-pad-start-end.md) | Pushes `padStart/padEnd` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
56
+ | [`prefer-string-match-all`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-match-all.md) | Pushes `String#matchAll` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
57
+ | [`prefer-string-raw`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-raw.md) | Pushes `String.raw` tag — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
58
+ | [`prefer-code-point`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-code-point.md) | Pushes `codePointAt/fromCodePoint` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
59
+ | [`prefer-array-find`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-find.md) | Pushes `Array#find/findLast` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
60
+ | [`prefer-array-some`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-some.md) | Pushes `Array#some` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
61
+ | [`prefer-array-index-of`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-index-of.md) | Pushes `findIndex/findLastIndex` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
62
+ | [`prefer-array-flat`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-flat.md) | Pushes `Array#flat` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
63
+ | [`prefer-array-flat-map`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-flat-map.md) | Pushes `Array#flatMap` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
64
+ | [`prefer-array-last-methods`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-last-methods.md) | Pushes `.at()/findLast` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
65
+ | [`prefer-array-from-async`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-from-async.md) | Pushes `Array.fromAsync` — missing + async unsupported | [Engine limitations](https://ssjs.guide/engine-limitations/) |
66
+ | [`no-array-reverse`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-array-reverse.md) | Autofixes to `Array#toReversed()` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
67
+ | [`prefer-at`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-at.md) | Pushes `.at()` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
68
+ | [`prefer-negative-index`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-negative-index.md) | Pushes `.at()` — missing; forbids the `.length - i` workaround | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
69
+ | [`prefer-spread`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-spread.md) | Pushes spread `...` — ES6 syntax, throws on ES3 | [Engine limitations](https://ssjs.guide/engine-limitations/) |
70
+ | [`prefer-date-now`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-date-now.md) | Pushes `Date.now()` — missing static | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
71
+ | [`prefer-object-from-entries`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-object-from-entries.md) | Pushes `Object.fromEntries` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
72
+ | [`prefer-reflect-apply`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-reflect-apply.md) | Pushes `Reflect.apply` — `Reflect` missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
73
+ | [`prefer-number-properties`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-number-properties.md) | Pushes `Number.parseInt/parseFloat/isNaN/isFinite` statics — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
74
+ | [`prefer-number-is-safe-integer`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-number-is-safe-integer.md) | Pushes `Number.isSafeInteger` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
75
+ | [`prefer-number-coercion`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-number-coercion.md) | Number-static patterns unsafe on the ES3 engine | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
76
+ | [`prefer-global-number-constants`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-global-number-constants.md) | Pushes `Number.NaN/Number.POSITIVE_INFINITY` etc. — missing statics | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
77
+ | [`prefer-native-coercion-functions`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-native-coercion-functions.md) | Native coercion refs that are missing/unsafe | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
78
+ | [`prefer-math-trunc`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-math-trunc.md) | Pushes `Math.trunc` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
79
+ | [`prefer-modern-math-apis`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-modern-math-apis.md) | Pushes `Math.log10/log2/hypot` — missing; forbids `Math.log(x)/Math.LN10` and `Math.sqrt(a*a+b*b)` workarounds | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
80
+ | [`no-instanceof-builtins`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-instanceof-builtins.md) | Autofixes `instanceof Array` to `Array.isArray` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
81
+ | [`no-for-each`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-for-each.md) | Assumes `.forEach` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
82
+ | [`prefer-set-has`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-set-has.md) | Pushes `Set` — ES6, unsupported | [Engine limitations](https://ssjs.guide/engine-limitations/) |
83
+ | [`prefer-set-size`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-set-size.md) | Pushes `Set` — ES6, unsupported | [Engine limitations](https://ssjs.guide/engine-limitations/) |
84
+ | [`prefer-set-methods`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-set-methods.md) | Pushes `Set` methods — ES2024, unsupported | [Engine limitations](https://ssjs.guide/engine-limitations/) |
85
+ | [`prefer-map-from-entries`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-map-from-entries.md) | Pushes `Map` + `Object.fromEntries` — unsupported | [Engine limitations](https://ssjs.guide/engine-limitations/) |
86
+ | [`prefer-group-by`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-group-by.md) | Pushes `Object.groupBy/Map.groupBy` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
87
+ | [`prefer-iterator-helpers`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-iterator-helpers.md) | Pushes the iterator-helper protocol — unsupported | [Engine limitations](https://ssjs.guide/engine-limitations/) |
88
+ | [`prefer-structured-clone`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-structured-clone.md) | Pushes `structuredClone` global — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
89
+ | [`require-array-join-separator`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/require-array-join-separator.md) | Safe alone, but grouped here to avoid pushing modern array idioms under the strict set | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
90
+
91
+ ### Group B — forbid ES6+ syntax / ES-module / async constructs (5)
92
+
93
+ | Rule | Why it breaks SSJS | SFMC evidence |
94
+ |---|---|---|
95
+ | [`prefer-optional-catch-binding`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-optional-catch-binding.md) | Pushes `catch {}` (ES2019) — may not parse on ES3 | [Engine limitations](https://ssjs.guide/engine-limitations/) |
96
+ | [`prefer-module`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-module.md) | Pushes ES modules — unsupported | [Engine limitations](https://ssjs.guide/engine-limitations/) |
97
+ | [`prefer-node-protocol`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-node-protocol.md) | Pushes `node:` imports — no module system | [Engine limitations](https://ssjs.guide/engine-limitations/) |
98
+ | [`prefer-top-level-await`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-top-level-await.md) | Pushes top-level `await` — async unsupported | [Engine limitations](https://ssjs.guide/engine-limitations/) |
99
+ | [`prefer-export-from`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-export-from.md) | Pushes `export … from` — ES modules | [Engine limitations](https://ssjs.guide/engine-limitations/) |
100
+
101
+ > **Note:** [`prefer-regexp-test`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-regexp-test.md) stays **active** — `RegExp#test` exists in SFMC SSJS, so it is intentionally **not** in the override list.
102
+
103
+ ---
104
+
105
+ ## Section 3 — Rules OK as-is (254)
17
106
 
18
107
  These recommended rules are **not** disabled by the override config. They are either genuinely SFMC-safe (readability / best-practice rules that work on the ES3/ES5 engine) or **inert** on SSJS — many target the DOM, Node.js, Promises, TypeScript, or ES modules and therefore never fire on server-side SFMC code. Each links to its official unicorn documentation.
19
108
 
@@ -274,92 +363,3 @@ These recommended rules are **not** disabled by the override config. They are ei
274
363
  - [throw-new-error](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/throw-new-error.md)
275
364
  <!-- END 254-OK-LIST -->
276
365
 
277
- ---
278
-
279
- ## Section 2 — Rules to override for SSJS (46)
280
-
281
- These 46 recommended rules either **autofix code to a missing built-in**, **forbid a documented SFMC workaround**, or **enforce ES-module / async / ES6-only syntax** the engine cannot run. The override config sets each to `'off'` for SSJS. All 46 are confirmed `recommended` in unicorn v71.1.0.
282
-
283
- ### Group A — autofix to a missing built-in / forbid a SFMC workaround (41)
284
-
285
- | Rule | Why it breaks SSJS | SFMC evidence |
286
- |---|---|---|
287
- | [`prefer-includes`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-includes.md) | Pushes `Array/String#includes()` — missing in SSJS | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
288
- | [`prefer-string-starts-ends-with`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-starts-ends-with.md) | Pushes `String#startsWith/endsWith` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
289
- | [`prefer-string-trim-start-end`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-trim-start-end.md) | Pushes `trimStart/trimEnd` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
290
- | [`prefer-string-slice`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-slice.md) | Forbids `substring`, the SFMC-safe choice | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
291
- | [`prefer-string-replace-all`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-replace-all.md) | Pushes `String#replaceAll` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
292
- | [`prefer-string-repeat`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-repeat.md) | Pushes `String#repeat` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
293
- | [`prefer-string-pad-start-end`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-pad-start-end.md) | Pushes `padStart/padEnd` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
294
- | [`prefer-string-match-all`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-match-all.md) | Pushes `String#matchAll` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
295
- | [`prefer-string-raw`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-raw.md) | Pushes `String.raw` tag — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
296
- | [`prefer-code-point`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-code-point.md) | Pushes `codePointAt/fromCodePoint` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
297
- | [`prefer-array-find`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-find.md) | Pushes `Array#find/findLast` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
298
- | [`prefer-array-some`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-some.md) | Pushes `Array#some` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
299
- | [`prefer-array-index-of`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-index-of.md) | Pushes `findIndex/findLastIndex` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
300
- | [`prefer-array-flat`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-flat.md) | Pushes `Array#flat` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
301
- | [`prefer-array-flat-map`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-flat-map.md) | Pushes `Array#flatMap` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
302
- | [`prefer-array-last-methods`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-last-methods.md) | Pushes `.at()/findLast` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
303
- | [`prefer-array-from-async`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-from-async.md) | Pushes `Array.fromAsync` — missing + async unsupported | [Engine limitations](https://ssjs.guide/engine-limitations/) |
304
- | [`no-array-reverse`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-array-reverse.md) | Autofixes to `Array#toReversed()` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
305
- | [`prefer-at`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-at.md) | Pushes `.at()` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
306
- | [`prefer-negative-index`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-negative-index.md) | Pushes `.at()` — missing; forbids the `.length - i` workaround | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
307
- | [`prefer-spread`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-spread.md) | Pushes spread `...` — ES6 syntax, throws on ES3 | [Engine limitations](https://ssjs.guide/engine-limitations/) |
308
- | [`prefer-date-now`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-date-now.md) | Pushes `Date.now()` — missing static | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
309
- | [`prefer-object-from-entries`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-object-from-entries.md) | Pushes `Object.fromEntries` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
310
- | [`prefer-reflect-apply`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-reflect-apply.md) | Pushes `Reflect.apply` — `Reflect` missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
311
- | [`prefer-number-properties`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-number-properties.md) | Pushes `Number.parseInt/parseFloat/isNaN/isFinite` statics — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
312
- | [`prefer-number-is-safe-integer`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-number-is-safe-integer.md) | Pushes `Number.isSafeInteger` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
313
- | [`prefer-number-coercion`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-number-coercion.md) | Number-static patterns unsafe on the ES3 engine | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
314
- | [`prefer-global-number-constants`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-global-number-constants.md) | Pushes `Number.NaN/Number.POSITIVE_INFINITY` etc. — missing statics | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
315
- | [`prefer-native-coercion-functions`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-native-coercion-functions.md) | Native coercion refs that are missing/unsafe | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
316
- | [`prefer-math-trunc`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-math-trunc.md) | Pushes `Math.trunc` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
317
- | [`prefer-modern-math-apis`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-modern-math-apis.md) | Pushes `Math.log10/log2/hypot` — missing; forbids `Math.log(x)/Math.LN10` and `Math.sqrt(a*a+b*b)` workarounds | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
318
- | [`no-instanceof-builtins`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-instanceof-builtins.md) | Autofixes `instanceof Array` to `Array.isArray` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
319
- | [`no-for-each`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-for-each.md) | Assumes `.forEach` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
320
- | [`prefer-set-has`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-set-has.md) | Pushes `Set` — ES6, unsupported | [Engine limitations](https://ssjs.guide/engine-limitations/) |
321
- | [`prefer-set-size`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-set-size.md) | Pushes `Set` — ES6, unsupported | [Engine limitations](https://ssjs.guide/engine-limitations/) |
322
- | [`prefer-set-methods`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-set-methods.md) | Pushes `Set` methods — ES2024, unsupported | [Engine limitations](https://ssjs.guide/engine-limitations/) |
323
- | [`prefer-map-from-entries`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-map-from-entries.md) | Pushes `Map` + `Object.fromEntries` — unsupported | [Engine limitations](https://ssjs.guide/engine-limitations/) |
324
- | [`prefer-group-by`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-group-by.md) | Pushes `Object.groupBy/Map.groupBy` — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
325
- | [`prefer-iterator-helpers`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-iterator-helpers.md) | Pushes the iterator-helper protocol — unsupported | [Engine limitations](https://ssjs.guide/engine-limitations/) |
326
- | [`prefer-structured-clone`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-structured-clone.md) | Pushes `structuredClone` global — missing | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
327
- | [`require-array-join-separator`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/require-array-join-separator.md) | Safe alone, but grouped here to avoid pushing modern array idioms under the strict set | [ECMAScript built-ins](https://ssjs.guide/ecmascript-builtins/) |
328
-
329
- ### Group B — forbid ES6+ syntax / ES-module / async constructs (5)
330
-
331
- | Rule | Why it breaks SSJS | SFMC evidence |
332
- |---|---|---|
333
- | [`prefer-optional-catch-binding`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-optional-catch-binding.md) | Pushes `catch {}` (ES2019) — may not parse on ES3 | [Engine limitations](https://ssjs.guide/engine-limitations/) |
334
- | [`prefer-module`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-module.md) | Pushes ES modules — unsupported | [Engine limitations](https://ssjs.guide/engine-limitations/) |
335
- | [`prefer-node-protocol`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-node-protocol.md) | Pushes `node:` imports — no module system | [Engine limitations](https://ssjs.guide/engine-limitations/) |
336
- | [`prefer-top-level-await`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-top-level-await.md) | Pushes top-level `await` — async unsupported | [Engine limitations](https://ssjs.guide/engine-limitations/) |
337
- | [`prefer-export-from`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-export-from.md) | Pushes `export … from` — ES modules | [Engine limitations](https://ssjs.guide/engine-limitations/) |
338
-
339
- > **Note:** [`prefer-regexp-test`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-regexp-test.md) stays **active** — `RegExp#test` exists in SFMC SSJS, so it is intentionally **not** in the override list.
340
-
341
- ---
342
-
343
- ## Section 3 — How to apply
344
-
345
- The override is **optional** and **SSJS-scoped**. `eslint-plugin-sfmc` never loads unicorn; the override is a plain rules object that only resolves when you have loaded your own unicorn config **earlier** in the flat-config array (that config registers the `unicorn` plugin). Spread the sfmc override **after** it:
346
-
347
- ```js
348
- import sfmc from 'eslint-plugin-sfmc';
349
- import eslintPluginUnicorn from 'eslint-plugin-unicorn';
350
-
351
- export default [
352
- eslintPluginUnicorn.configs.recommended, // you opt in — registers the `unicorn` plugin
353
- ...sfmc.configs.recommended,
354
- ...sfmc.configs['unicorn-ssjs'], // OPTIONAL: off the 46 SFMC-incompatible unicorn rules for SSJS
355
- // For SSJS embedded in HTML, also add:
356
- // ...sfmc.configs['unicorn-ssjs-embedded'],
357
- ];
358
- ```
359
-
360
- | Config | Applies to |
361
- |---|---|
362
- | `unicorn-ssjs` | `**/*.ssjs` |
363
- | `unicorn-ssjs-embedded` | `**/*.html/*.js` (SSJS extracted from `<script runat="server">`) |
364
-
365
- If you don't use unicorn, omit these configs entirely — nothing else in `eslint-plugin-sfmc` references them.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-sfmc",
3
- "version": "4.1.0",
3
+ "version": "4.1.1",
4
4
  "description": "ESLint plugin for Salesforce Marketing Cloud Engagement+Next - AMPscript, Server-Side JavaScript (SSJS) and Handlebars",
5
5
  "type": "module",
6
6
  "main": "src/index.js",