refactor progress

This commit is contained in:
Hampus Kraft
2026-02-17 12:22:36 +00:00
parent cb31608523
commit d5abd1a7e4
8257 changed files with 1190207 additions and 761040 deletions

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import {Locales} from '@fluxer/constants/src/Locales';
import {getCachedListFormatter} from '@fluxer/list_utils/src/ListFormattingCache';
import {formatListWithFallback} from '@fluxer/list_utils/src/ListFormattingFallback';
import {isIntlListFormatLocaleSupported, isIntlListFormatSupported} from '@fluxer/list_utils/src/ListFormattingSupport';
import type {
IListFormatter,
ListFormatOptions,
ListFormatStyle,
ListFormatType,
ListFormatterConfig,
ResolvedListFormatterConfig,
} from '@fluxer/list_utils/src/ListFormattingTypes';
const DEFAULT_LOCALE = Locales.EN_US;
const DEFAULT_LIST_FORMAT_STYLE: ListFormatStyle = 'long';
const DEFAULT_LIST_FORMAT_TYPE: ListFormatType = 'conjunction';
export function isListFormatSupported(): boolean {
return isIntlListFormatSupported();
}
function normalizeLocale(locale: string): string {
if (!isIntlListFormatLocaleSupported(locale)) {
return DEFAULT_LOCALE;
}
return locale;
}
function resolveListFormatterConfig(config: ListFormatterConfig): ResolvedListFormatterConfig {
const requestedLocale = config.locale?.trim();
const locale = requestedLocale == null || requestedLocale === '' ? DEFAULT_LOCALE : normalizeLocale(requestedLocale);
const style = config.style ?? DEFAULT_LIST_FORMAT_STYLE;
const type = config.type ?? DEFAULT_LIST_FORMAT_TYPE;
return {
locale,
style,
type,
};
}
function formatWithIntl(items: ReadonlyArray<string>, config: ResolvedListFormatterConfig): string {
try {
return getCachedListFormatter(config).format(items);
} catch {
return formatListWithFallback(items, config.type);
}
}
function formatItems(items: ReadonlyArray<string>, config: ResolvedListFormatterConfig): string {
if (items.length === 0) {
return '';
}
if (items.length === 1) {
return items[0] ?? '';
}
if (!isListFormatSupported()) {
return formatListWithFallback(items, config.type);
}
return formatWithIntl(items, config);
}
export function formatListWithConfig(items: ReadonlyArray<string>, config: ListFormatterConfig = {}): string {
const resolvedConfig = resolveListFormatterConfig(config);
return formatItems(items, resolvedConfig);
}
export function createListFormatter(config: ListFormatterConfig = {}): IListFormatter {
const resolvedConfig = resolveListFormatterConfig(config);
return {
format(items: ReadonlyArray<string>): string {
return formatItems(items, resolvedConfig);
},
};
}
export function formatList(
items: Array<string>,
locale: string = DEFAULT_LOCALE,
options: ListFormatOptions = {},
): string {
return formatListWithConfig(items, {
locale,
style: options.style,
type: options.type,
});
}

View File

@@ -0,0 +1,38 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import type {ResolvedListFormatterConfig} from '@fluxer/list_utils/src/ListFormattingTypes';
const formatterCache = new Map<string, Intl.ListFormat>();
export function getCachedListFormatter(config: ResolvedListFormatterConfig): Intl.ListFormat {
const cacheKey = `${config.locale}:${config.style}:${config.type}`;
const cachedFormatter = formatterCache.get(cacheKey);
if (cachedFormatter != null) {
return cachedFormatter;
}
const formatter = new Intl.ListFormat(config.locale, {
style: config.style,
type: config.type,
});
formatterCache.set(cacheKey, formatter);
return formatter;
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
import type {ListFormatType} from '@fluxer/list_utils/src/ListFormattingTypes';
function getFallbackConjunction(type: ListFormatType): string {
if (type === 'disjunction') {
return 'or';
}
return 'and';
}
export function formatListWithFallback(items: ReadonlyArray<string>, type: ListFormatType): string {
if (items.length === 0) {
return '';
}
if (items.length === 1) {
return items[0] ?? '';
}
if (type === 'unit') {
return items.join(', ');
}
const conjunction = getFallbackConjunction(type);
if (items.length === 2) {
return `${items[0]} ${conjunction} ${items[1]}`;
}
const lastItem = items[items.length - 1];
const leadingItems = items.slice(0, -1).join(', ');
return `${leadingItems}, ${conjunction} ${lastItem}`;
}

View File

@@ -0,0 +1,34 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
export function isIntlListFormatSupported(): boolean {
return typeof Intl !== 'undefined' && typeof Intl.ListFormat !== 'undefined';
}
export function isIntlListFormatLocaleSupported(locale: string): boolean {
if (!isIntlListFormatSupported()) {
return false;
}
try {
return Intl.ListFormat.supportedLocalesOf([locale]).length > 0;
} catch {
return false;
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
*/
export type ListFormatStyle = 'long' | 'short' | 'narrow';
export type ListFormatType = 'conjunction' | 'disjunction' | 'unit';
export interface ListFormatOptions {
style?: ListFormatStyle;
type?: ListFormatType;
}
export interface ListFormatterConfig extends ListFormatOptions {
locale?: string;
}
export interface ResolvedListFormatterConfig {
locale: string;
style: ListFormatStyle;
type: ListFormatType;
}
export interface IListFormatter {
format(items: ReadonlyArray<string>): string;
}