Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 0 additions & 48 deletions .eslintrc.yaml

This file was deleted.

72 changes: 0 additions & 72 deletions eslint-base.yaml

This file was deleted.

141 changes: 141 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import js from "@eslint/js";
import eslintConfigPrettier from "eslint-config-prettier";
import mochaPlugin from "eslint-plugin-mocha";
import globals from "globals";

import tseslint from "typescript-eslint";

export default [
{
ignores: [
"**/node_modules/",
"*/coverage/",
"*/dist/",
"*/esm/",
"*/vendor/",
"fluent-*/index.js",
"html/",
"tools/",
],
},
{
languageOptions: {
ecmaVersion: 2018,
sourceType: "module",
},
},

// Config files
{
files: ["**/*.mjs"],
languageOptions: { ecmaVersion: 2020 },
},
{
files: ["**/*.cjs"],
languageOptions: { globals: { ...globals.node } },
},

js.configs.recommended,
{
files: ["**/*.js", "**/*.mjs", "*/src/*.ts"],
rules: {
"consistent-return": "warn",
"dot-notation": "error",
eqeqeq: "error",
"max-depth": ["error", 6],
"no-caller": "error",
"no-console": "warn",
"no-constant-condition": ["warn", { checkLoops: false }],
"no-duplicate-imports": "error",
"no-else-return": "error",
"no-empty": "warn",
"no-eval": "error",
"no-extend-native": "error",
"no-extra-bind": "error",
"no-implicit-globals": "error",
"no-implied-eval": "error",
"no-iterator": "error",
"no-loop-func": "error",
"no-multi-str": "error",
"no-nested-ternary": "error",
"no-proto": "error",
"no-sequences": "error",
"no-shadow": "error",
"no-undef-init": "error",
"no-unneeded-ternary": "error",
"no-unreachable": "warn",
"no-unused-vars": "warn",
"no-use-before-define": ["error", { functions: false, classes: false }],
"no-useless-call": "error",
"no-useless-concat": "error",
"no-useless-return": "error",
"prefer-arrow-callback": "warn",
"prefer-rest-params": "error",
"prefer-spread": "error",
"prefer-template": "error",
"spaced-comment": ["error", "always"],
strict: ["error", "global"],
},
},

// TypeScript
...tseslint.configs.recommendedTypeChecked.map(cfg => ({
...cfg,
files: ["**/*.ts"],
})),
{
files: ["**/*.ts"],
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname,
},
},
rules: {
complexity: "off",
"prefer-const": "off",
"no-undef": "off",
"no-unused-vars": ["error", { args: "none" }],
"no-use-before-define": "off",
"@typescript-eslint/no-inferrable-types": "off",
"@typescript-eslint/no-unused-vars": ["error", { args: "none" }],
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/explicit-function-return-type": "error",
},
},
eslintConfigPrettier,

// Test suites
{
files: ["*/test/**"],
languageOptions: {
globals: { ...globals.mocha, ...globals.node },
ecmaVersion: 2020,
},
plugins: { mocha: mochaPlugin },
rules: {
"mocha/no-exclusive-tests": "error",
"mocha/no-identical-title": "error",
"no-console": "off",
"prefer-arrow-callback": "off",
},
},
{
files: ["fluent-dom/test/*"],
languageOptions: { globals: { ...globals.browser } },
},
{
files: ["fluent-react/test/**"],
languageOptions: {
globals: { ...globals.browser, ...globals.jest },
ecmaVersion: 2020,
parserOptions: { ecmaFeatures: { jsx: true } },
},
plugins: { mocha: mochaPlugin },
rules: {
"mocha/no-exclusive-tests": "error",
"mocha/no-identical-title": "error",
"no-unused-vars": "off",
},
},
];
1 change: 0 additions & 1 deletion fluent-bundle/src/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,6 @@ export class FluentResource {
// Normalize a blank block and extract the indent details.
function makeIndent(blank: string): Indent {
let value = blank.replace(RE_BLANK_LINES, "\n");
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
let length = RE_INDENT.exec(blank)![1].length;
return new Indent(value, length);
}
Expand Down
2 changes: 2 additions & 0 deletions fluent-bundle/src/scope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ export class Scope {
}
let id = JSON.stringify(opts);
if (!cache[id]) {
// @ts-expect-error This is fine.
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
cache[id] = new ctor(this.bundle.locales, opts);
}
return cache[id];
Expand Down
48 changes: 24 additions & 24 deletions fluent-bundle/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,36 +127,35 @@ export class FluentNumber extends FluentType<number> {
* option bag of options which will be passed to `Intl.DateTimeFormat` when the
* `FluentDateTime` is formatted to a string.
*/
export class FluentDateTime extends FluentType<
| number
| Date
| TemporalObject
> {
export class FluentDateTime extends FluentType<number | Date | TemporalObject> {
/** Options passed to `Intl.DateTimeFormat`. */
public opts: Intl.DateTimeFormatOptions;

static supportsValue(value: unknown): value is ConstructorParameters<typeof FluentDateTime>[0] {
static supportsValue(
value: unknown
): value is ConstructorParameters<typeof FluentDateTime>[0] {
if (typeof value === "number") return true;
if (value instanceof Date) return true;
if (value instanceof FluentType) return FluentDateTime.supportsValue(value.valueOf());
if (value instanceof FluentType)
return FluentDateTime.supportsValue(value.valueOf());
// Temporary workaround to support environments without Temporal
if ('Temporal' in globalThis) {
if ("Temporal" in globalThis) {
// for TypeScript, which doesn't know about Temporal yet
const _Temporal = (
globalThis as unknown as { Temporal: Record<string, () => unknown> }
).Temporal;
if (
value instanceof _Temporal.Instant ||
value instanceof _Temporal.PlainDateTime ||
value instanceof _Temporal.PlainDate ||
value instanceof _Temporal.PlainMonthDay ||
value instanceof _Temporal.PlainTime ||
value instanceof _Temporal.Instant ||
value instanceof _Temporal.PlainDateTime ||
value instanceof _Temporal.PlainDate ||
value instanceof _Temporal.PlainMonthDay ||
value instanceof _Temporal.PlainTime ||
value instanceof _Temporal.PlainYearMonth
) {
return true;
}
}
return false
return false;
}

/**
Expand All @@ -167,12 +166,7 @@ export class FluentDateTime extends FluentType<
* @param opts Options which will be passed to `Intl.DateTimeFormat`.
*/
constructor(
value:
| number
| Date
| TemporalObject
| FluentDateTime
| FluentType<number>,
value: number | Date | TemporalObject | FluentDateTime | FluentType<number>,
opts: Intl.DateTimeFormatOptions = {}
) {
// unwrap any FluentType value, but only retain the opts from FluentDateTime
Expand All @@ -184,7 +178,11 @@ export class FluentDateTime extends FluentType<
}

// Intl.DateTimeFormat defaults to gregorian calendar, but Temporal defaults to iso8601
if (typeof value === "object" && 'calendarId' in value && opts.calendar === undefined) {
if (
typeof value === "object" &&
"calendarId" in value &&
opts.calendar === undefined
) {
opts = { ...opts, calendar: value.calendarId };
}

Expand All @@ -202,11 +200,11 @@ export class FluentDateTime extends FluentType<
if (typeof value === "number") return value;
if (value instanceof Date) return value.getTime();

if ('epochMilliseconds' in value) {
if ("epochMilliseconds" in value) {
return value.epochMilliseconds as number;
}

if ('toZonedDateTime' in value) {
if ("toZonedDateTime" in value) {
return value.toZonedDateTime!("UTC").epochMilliseconds;
}

Expand All @@ -219,7 +217,9 @@ export class FluentDateTime extends FluentType<
toString(scope: Scope): string {
try {
const dtf = scope.memoizeIntlObject(Intl.DateTimeFormat, this.opts);
return dtf.format(this.value as Parameters<Intl.DateTimeFormat["format"]>[0]);
return dtf.format(
this.value as Parameters<Intl.DateTimeFormat["format"]>[0]
);
} catch (err) {
scope.reportError(err);
if (typeof this.value === "number" || this.value instanceof Date) {
Expand Down
Loading