Skip to content

Commit a749c7e

Browse files
authored
Add rules for Intl.DurationFormat (#236)
1 parent 1e99295 commit a749c7e

22 files changed

+560
-13
lines changed

docs/configs/index.md

+26
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,32 @@ export default [
2828
}
2929
```
3030

31+
## no-new-in-esnext-intl-api
32+
33+
disallow the new stuff to be planned for the next yearly ECMAScript Intl API (ECMA-402) snapshot.\
34+
⚠️ This config will be changed in the minor versions of this plugin.
35+
36+
### [Config (Flat Config)]
37+
38+
eslint.config.js:
39+
40+
```js
41+
import pluginESx from "eslint-plugin-es-x"
42+
export default [
43+
pluginESx.configs['flat/no-new-in-esnext-intl-api']
44+
]
45+
```
46+
47+
### [Legacy Config]
48+
49+
.eslintrc.*:
50+
51+
```json
52+
{
53+
"extends": ["plugin:es-x/no-new-in-esnext-intl-api"],
54+
}
55+
```
56+
3157
## no-new-in-es2024
3258

3359
disallow new stuff in ES2024.

docs/rules/index.md

+11
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ There is a config that enables the rules in this category: [`no-new-in-esnext`]
3838
| [es-x/no-set-prototype-union](./no-set-prototype-union.md) | disallow the `Set.prototype.union` method. | |
3939
| [es-x/no-trailing-dynamic-import-commas](./no-trailing-dynamic-import-commas.md) | disallow trailing commas in `import()`. | 🔧 |
4040

41+
## ES2025 Intl API
42+
43+
There is a config that enables the rules in this category: [`no-new-in-esnext-intl-api`]
44+
45+
| Rule ID | Description | |
46+
|:--------|:------------|:--:|
47+
| [es-x/no-intl-durationformat](./no-intl-durationformat.md) | disallow the `Intl.DurationFormat` object. | |
48+
4149
## ES2024
4250

4351
There are multiple configs that enable all rules in this category: [`no-new-in-es2024`], [`restrict-to-es3`], [`restrict-to-es5`], [`restrict-to-es2015`], [`restrict-to-es2016`], [`restrict-to-es2017`], [`restrict-to-es2018`], [`restrict-to-es2019`], [`restrict-to-es2020`], [`restrict-to-es2021`], [`restrict-to-es2022`], and [`restrict-to-es2023`]
@@ -407,6 +415,8 @@ Rules in this category are not included in any preset.
407415
| [es-x/no-nonstandard-intl-datetimeformat-prototype-properties](./no-nonstandard-intl-datetimeformat-prototype-properties.md) | disallow non-standard properties on Intl.DateTimeFormat instance. | |
408416
| [es-x/no-nonstandard-intl-displaynames-properties](./no-nonstandard-intl-displaynames-properties.md) | disallow non-standard static properties on `Intl.DisplayNames` class. | |
409417
| [es-x/no-nonstandard-intl-displaynames-prototype-properties](./no-nonstandard-intl-displaynames-prototype-properties.md) | disallow non-standard properties on Intl.DisplayNames instance. | |
418+
| [es-x/no-nonstandard-intl-durationformat-properties](./no-nonstandard-intl-durationformat-properties.md) | disallow non-standard static properties on `Intl.DurationFormat` class. | |
419+
| [es-x/no-nonstandard-intl-durationformat-prototype-properties](./no-nonstandard-intl-durationformat-prototype-properties.md) | disallow non-standard properties on Intl.DurationFormat instance. | |
410420
| [es-x/no-nonstandard-intl-listformat-properties](./no-nonstandard-intl-listformat-properties.md) | disallow non-standard static properties on `Intl.ListFormat` class. | |
411421
| [es-x/no-nonstandard-intl-listformat-prototype-properties](./no-nonstandard-intl-listformat-prototype-properties.md) | disallow non-standard properties on Intl.ListFormat instance. | |
412422
| [es-x/no-nonstandard-intl-locale-properties](./no-nonstandard-intl-locale-properties.md) | disallow non-standard static properties on `Intl.Locale` class. | |
@@ -464,6 +474,7 @@ Rules in this category are not included in any preset.
464474
| [es-x/no-string-prototype-iswellformed-towellformed](./no-string-prototype-iswellformed-towellformed.md) | [es-x/no-string-prototype-iswellformed](./no-string-prototype-iswellformed.md), [es-x/no-string-prototype-towellformed](./no-string-prototype-towellformed.md) |
465475

466476
[`no-new-in-esnext`]: ../configs/index.md#no-new-in-esnext
477+
[`no-new-in-esnext-intl-api`]: ../configs/index.md#no-new-in-esnext-intl-api
467478
[`no-new-in-es2024`]: ../configs/index.md#no-new-in-es2024
468479
[`restrict-to-es2023`]: ../configs/index.md#restrict-to-es2023
469480
[`restrict-to-es2023-intl-api`]: ../configs/index.md#restrict-to-es2023-intl-api

docs/rules/no-intl-durationformat.md

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
title: "es-x/no-intl-durationformat"
3+
description: "disallow the `Intl.DurationFormat` object"
4+
---
5+
6+
# es-x/no-intl-durationformat
7+
> disallow the `Intl.DurationFormat` object
8+
9+
- ❗ <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge>
10+
- ✅ The following configurations enable this rule: [no-new-in-esnext-intl-api]
11+
12+
This rule reports ES2025 Intl API `Intl.DurationFormat` object as errors.
13+
14+
## 💡 Examples
15+
16+
⛔ Examples of **incorrect** code for this rule:
17+
18+
<eslint-playground type="bad">
19+
20+
```js
21+
/*eslint es-x/no-intl-durationformat: error */
22+
const df = new Intl.DurationFormat("fr-FR", { style: "long" });
23+
24+
df.format({
25+
hours: 1,
26+
minutes: 46,
27+
seconds: 40,
28+
});
29+
```
30+
31+
</eslint-playground>
32+
33+
## 📚 References
34+
35+
- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-intl-durationformat.js)
36+
- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-intl-durationformat.js)
37+
38+
[no-new-in-esnext-intl-api]: ../configs/index.md#no-new-in-esnext-intl-api
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
title: "es-x/no-nonstandard-intl-durationformat-properties"
3+
description: "disallow non-standard static properties on `Intl.DurationFormat` class"
4+
---
5+
6+
# es-x/no-nonstandard-intl-durationformat-properties
7+
> disallow non-standard static properties on `Intl.DurationFormat` class
8+
9+
- ❗ <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge>
10+
11+
This rule reports non-standard static properties on `Intl.DurationFormat` class as errors.
12+
13+
## 💡 Examples
14+
15+
⛔ Examples of **incorrect** code for this rule:
16+
17+
<eslint-playground type="bad">
18+
19+
```js
20+
/*eslint es-x/no-nonstandard-intl-durationformat-properties: error */
21+
Intl.DurationFormat.unknown();
22+
```
23+
24+
</eslint-playground>
25+
26+
## 🔧 Options
27+
28+
This rule has an option.
29+
30+
```jsonc
31+
{
32+
"rules": {
33+
"es-x/no-nonstandard-intl-durationformat-properties": [
34+
"error",
35+
{
36+
"allow": []
37+
}
38+
]
39+
}
40+
}
41+
```
42+
43+
### allow: string[]
44+
45+
An array of non-standard property names to allow.
46+
47+
## 📚 References
48+
49+
- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-nonstandard-intl-durationformat-properties.js)
50+
- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-nonstandard-intl-durationformat-properties.js)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---
2+
title: "es-x/no-nonstandard-intl-durationformat-prototype-properties"
3+
description: "disallow non-standard properties on Intl.DurationFormat instance"
4+
---
5+
6+
# es-x/no-nonstandard-intl-durationformat-prototype-properties
7+
> disallow non-standard properties on Intl.DurationFormat instance
8+
9+
- ❗ <badge text="This rule has not been released yet." vertical="middle" type="error"> ***This rule has not been released yet.*** </badge>
10+
11+
This rule reports non-standard properties on Intl.DurationFormat instance as errors.
12+
13+
## 💡 Examples
14+
15+
⛔ Examples of **incorrect** code for this rule:
16+
17+
<eslint-playground type="bad">
18+
19+
```js
20+
/*eslint es-x/no-nonstandard-intl-durationformat-prototype-properties: error */
21+
const df = new Intl.DurationFormat("fr-FR", { style: "long" });
22+
df.unknown();
23+
```
24+
25+
</eslint-playground>
26+
27+
## 🔧 Options
28+
29+
This rule has an option.
30+
31+
```jsonc
32+
{
33+
"rules": {
34+
"es-x/no-nonstandard-intl-durationformat-prototype-properties": [
35+
"error",
36+
{
37+
"allow": []
38+
}
39+
]
40+
}
41+
}
42+
```
43+
44+
### allow: string[]
45+
46+
An array of non-standard property names to allow.
47+
48+
## 📚 References
49+
50+
- [Rule source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js)
51+
- [Test source](https://github.com/eslint-community/eslint-plugin-es-x/blob/master/tests/lib/rules/no-nonstandard-intl-durationformat-prototype-properties.js)

lib/configs/flat/no-new-in-esnext-intl-api.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ module.exports = {
1010
return require("../../index.js")
1111
},
1212
},
13-
rules: {},
13+
rules: { "es-x/no-intl-durationformat": "error" },
1414
}

lib/configs/no-new-in-esnext-intl-api.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,7 @@
44
*/
55
"use strict"
66

7-
module.exports = { plugins: ["es-x"], rules: {} }
7+
module.exports = {
8+
plugins: ["es-x"],
9+
rules: { "es-x/no-intl-durationformat": "error" },
10+
}

lib/index.js

+3
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ module.exports = {
213213
"no-intl-datetimeformat-prototype-formatrange": require("./rules/no-intl-datetimeformat-prototype-formatrange"),
214214
"no-intl-datetimeformat-prototype-formattoparts": require("./rules/no-intl-datetimeformat-prototype-formattoparts"),
215215
"no-intl-displaynames": require("./rules/no-intl-displaynames"),
216+
"no-intl-durationformat": require("./rules/no-intl-durationformat"),
216217
"no-intl-getcanonicallocales": require("./rules/no-intl-getcanonicallocales"),
217218
"no-intl-listformat": require("./rules/no-intl-listformat"),
218219
"no-intl-locale": require("./rules/no-intl-locale"),
@@ -287,6 +288,8 @@ module.exports = {
287288
"no-nonstandard-intl-datetimeformat-prototype-properties": require("./rules/no-nonstandard-intl-datetimeformat-prototype-properties"),
288289
"no-nonstandard-intl-displaynames-properties": require("./rules/no-nonstandard-intl-displaynames-properties"),
289290
"no-nonstandard-intl-displaynames-prototype-properties": require("./rules/no-nonstandard-intl-displaynames-prototype-properties"),
291+
"no-nonstandard-intl-durationformat-properties": require("./rules/no-nonstandard-intl-durationformat-properties"),
292+
"no-nonstandard-intl-durationformat-prototype-properties": require("./rules/no-nonstandard-intl-durationformat-prototype-properties"),
290293
"no-nonstandard-intl-listformat-properties": require("./rules/no-nonstandard-intl-listformat-properties"),
291294
"no-nonstandard-intl-listformat-prototype-properties": require("./rules/no-nonstandard-intl-listformat-prototype-properties"),
292295
"no-nonstandard-intl-locale-properties": require("./rules/no-nonstandard-intl-locale-properties"),

lib/rules/no-intl-durationformat.js

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"use strict"
2+
3+
const {
4+
defineStaticPropertiesHandler,
5+
} = require("../util/define-static-properties-handler")
6+
7+
module.exports = {
8+
meta: {
9+
docs: {
10+
description: "disallow the `Intl.DurationFormat` object.",
11+
category: "ES2025-Intl-API",
12+
recommended: false,
13+
url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-intl-durationformat.html",
14+
},
15+
fixable: null,
16+
messages: {
17+
forbidden: "ES2025 Intl API '{{name}}' object is forbidden.",
18+
},
19+
schema: [],
20+
type: "problem",
21+
},
22+
create(context) {
23+
return defineStaticPropertiesHandler(context, {
24+
Intl: ["DurationFormat"],
25+
})
26+
},
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
"use strict"
2+
3+
const {
4+
defineNonstandardStaticPropertiesHandler,
5+
} = require("../util/define-nonstandard-static-properties-handler")
6+
const {
7+
intlDurationFormatProperties,
8+
} = require("../util/well-known-properties")
9+
10+
module.exports = {
11+
meta: {
12+
docs: {
13+
description:
14+
"disallow non-standard static properties on `Intl.DurationFormat` class",
15+
category: "nonstandard",
16+
recommended: false,
17+
url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-nonstandard-intl-durationformat-properties.html",
18+
},
19+
fixable: null,
20+
messages: {
21+
forbidden: "Non-standard '{{name}}' property is forbidden.",
22+
},
23+
schema: [
24+
{
25+
type: "object",
26+
properties: {
27+
allow: {
28+
type: "array",
29+
items: { type: "string" },
30+
uniqueItems: true,
31+
},
32+
},
33+
additionalProperties: false,
34+
},
35+
],
36+
type: "problem",
37+
},
38+
create(context) {
39+
/** @type {Set<string>} */
40+
const allows = new Set([
41+
...(context.options[0]?.allow || []),
42+
...intlDurationFormatProperties,
43+
])
44+
return defineNonstandardStaticPropertiesHandler(context, {
45+
"Intl.DurationFormat": allows,
46+
})
47+
},
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
"use strict"
2+
3+
const {
4+
defineNonstandardPrototypePropertiesHandler,
5+
} = require("../util/define-nonstandard-prototype-properties-handler")
6+
const {
7+
intlDurationFormatPrototypeProperties,
8+
} = require("../util/well-known-properties")
9+
10+
module.exports = {
11+
meta: {
12+
docs: {
13+
description:
14+
"disallow non-standard properties on Intl.DurationFormat instance",
15+
category: "nonstandard",
16+
recommended: false,
17+
url: "http://eslint-community.github.io/eslint-plugin-es-x/rules/no-nonstandard-intl-durationformat-prototype-properties.html",
18+
},
19+
fixable: null,
20+
messages: {
21+
forbidden: "Non-standard '{{name}}' property is forbidden.",
22+
},
23+
schema: [
24+
{
25+
type: "object",
26+
properties: {
27+
allow: {
28+
type: "array",
29+
items: { type: "string" },
30+
uniqueItems: true,
31+
},
32+
},
33+
additionalProperties: false,
34+
},
35+
],
36+
type: "problem",
37+
},
38+
create(context) {
39+
/** @type {Set<string>} */
40+
const allows = new Set([
41+
...(context.options[0]?.allow || []),
42+
...intlDurationFormatPrototypeProperties,
43+
])
44+
return defineNonstandardPrototypePropertiesHandler(context, {
45+
"Intl.DurationFormat": allows,
46+
})
47+
},
48+
}

lib/util/type-checker/es-types.js

+5
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,11 @@ const WELLKNOWN_GLOBALS = {
337337
return: { type: "Intl.DisplayNames" },
338338
prototypeType: "Intl.DisplayNames",
339339
},
340+
DurationFormat: {
341+
type: "Function",
342+
return: { type: "Intl.DurationFormat" },
343+
prototypeType: "Intl.DurationFormat",
344+
},
340345
Locale: {
341346
type: "Function",
342347
return: { type: "Intl.Locale" },

lib/util/type-checker/types.d.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export type TypeName =
1111
| "Intl.Segmenter"
1212
| "Intl.DisplayNames"
1313
| "Intl.Locale"
14+
| "Intl.DurationFormat"
1415
| "Promise"
1516
| "RegExp"
1617
| "String"
@@ -193,7 +194,7 @@ export type FinalizationRegistryPrototypeProperty = Exclude<
193194
keyof FinalizationRegistry<any>,
194195
ExcludePrototypeProperty
195196
>;
196-
export type IntlProperty = Exclude<keyof typeof Intl, ExcludeProperty>;
197+
export type IntlProperty = Exclude<keyof typeof Intl, ExcludeProperty> | 'DurationFormat';
197198
export type IteratorProperty = Exclude<keyof typeof Iterator, ExcludeProperty>;
198199
export type IteratorPrototypeProperty = Exclude<
199200
keyof IteratorObject<any>,

0 commit comments

Comments
 (0)