Добавлен browserslist-to-targets
This commit is contained in:
47
packages/browserslist-to-targets/README.md
Normal file
47
packages/browserslist-to-targets/README.md
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# @advdominion/browserslist-to-targets
|
||||||
|
|
||||||
|
Преобразует конфиг [browserslist](https://github.com/browserslist/browserslist) в массив target-строк, совместимый с [esbuild](https://esbuild.github.io) и [Oxc](https://oxc-project.github.io).
|
||||||
|
|
||||||
|
## Зачем
|
||||||
|
|
||||||
|
Оба инструмента (esbuild и Oxc) понимают ограниченный набор целевых браузеров, который отличается от browserslist. Пакет приводит результат `browserslist()` к короткому esbuild-формату: `["chrome109", "ios18.5"]`, а всё, что esbuild/Oxc не поддерживает (`and_chr`, `kaios`, `samsung` и т.д.) — отбрасывает.
|
||||||
|
|
||||||
|
## Установка
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn add -D @advdominion/browserslist-to-targets
|
||||||
|
```
|
||||||
|
|
||||||
|
## Использование
|
||||||
|
|
||||||
|
```js
|
||||||
|
import browserslist from 'browserslist';
|
||||||
|
import { browserslistToTargets } from '@advdominion/browserslist-to-targets';
|
||||||
|
|
||||||
|
const targets = browserslistToTargets(browserslist());
|
||||||
|
// ["chrome109", "edge149", "firefox140", "ios18.5", "opera127", "safari26.5"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### `browserslistToTargets(browsers): string[]`
|
||||||
|
|
||||||
|
- `browsers` — массив строк от `browserslist()`, например `["chrome 151", "ios_saf 26.6"]`.
|
||||||
|
- Возвращает массив target-строк без пробела: `["chrome151", "ios26.5"]`.
|
||||||
|
|
||||||
|
## Правила преобразования
|
||||||
|
|
||||||
|
| browserslist | esbuild/Oxc | Примечание |
|
||||||
|
| ------------------------------------------------- | --------------- | ------------------------------------------ |
|
||||||
|
| `chrome 151` | `chrome151` | версия становится «приклеенной» к имени |
|
||||||
|
| `ios_saf 26.6` | `ios26.5` | `ios_saf → ios`, остаётся самая старая |
|
||||||
|
| `ios_saf 25-26.5` | `ios25` | `ios_saf → ios`, диапазон → нижняя граница |
|
||||||
|
| `android 151` | `chrome151` | `android → chrome` |
|
||||||
|
| `ios 26.0` | `ios26` | убирает завершающий `.0` |
|
||||||
|
| `and_chr`, `kaios`, `samsung`, `op_mob`, `and_ff` | — отбрасывается | нет в esbuild/Oxc |
|
||||||
|
|
||||||
|
Для каждого браузера остаётся самая старая версия — трансформации покрывают самую консервативную цель.
|
||||||
|
|
||||||
|
## Лицензия
|
||||||
|
|
||||||
|
MIT
|
||||||
65
packages/browserslist-to-targets/index.js
Normal file
65
packages/browserslist-to-targets/index.js
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/**
|
||||||
|
* Браузеры, поддерживаемые esbuild/Oxc.
|
||||||
|
*
|
||||||
|
* Зачем: browserslist как входной конфиг должен быть приведён к целевому
|
||||||
|
* формату, который понимает минификатор/трансформер. У esbuild и Oxc
|
||||||
|
* список целевых браузеров жёстко ограничен и отличается от browserslist.
|
||||||
|
* Поэтому мы транслируем браузеры из browserslist в короткий esbuild-формат,
|
||||||
|
* а всё, чего в нём нет — отбрасываем.
|
||||||
|
*/
|
||||||
|
const SUPPORTED_TARGETS = new Set(['es', 'chrome', 'edge', 'firefox', 'ios', 'node', 'safari', 'opera', 'ie']);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Соответствие идентификаторов браузеров browserslist тем, что знает esbuild.
|
||||||
|
*
|
||||||
|
* Browserslist различает `ios_saf` (Safari на iOS) и `android` (Chrome на
|
||||||
|
* Android), тогда как esbuild знает общее `ios` и `chrome`.
|
||||||
|
*/
|
||||||
|
const REPLACES = {
|
||||||
|
ios_saf: 'ios',
|
||||||
|
android: 'chrome',
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Преобразует результат `browserslist()` в массив target-строк для esbuild/Oxc.
|
||||||
|
*
|
||||||
|
* Вход — массив записей вида `"chrome 109"`, `"ios_saf 18.5-18.7"`.
|
||||||
|
* Выход — массив вида `["chrome109", "ios18.5"]`.
|
||||||
|
*
|
||||||
|
* Шаги:
|
||||||
|
* 1. Режем запись на имя и версию.
|
||||||
|
* 2. Подменяем идентификаторы (`ios_saf → ios`, `android → chrome`).
|
||||||
|
* 3. Диапазоны версий сводим к нижней границе (`18.5-18.7 → 18.5`).
|
||||||
|
* 4. Приводим `18.0` к `18` (убираем хвостовой `.0`).
|
||||||
|
* 5. Отбрасываем версии, не проходящие regex (ломают esbuild), и браузеры,
|
||||||
|
* которых нет в `SUPPORTED_TARGETS` (`and_chr`, `kaios`, `samsung` и т.д.).
|
||||||
|
* 6. Для каждого браузера оставляем самую старую версию — esbuild применяет
|
||||||
|
* трансформации, покрывающие самую консервативную цель.
|
||||||
|
* 7. Собираем целевые строки без пробела: `chrome109`.
|
||||||
|
*
|
||||||
|
* @param {string[]} browsers - массив строк браузеров от `browserslist()`.
|
||||||
|
* @returns {string[]} массив target-строк совместимый с esbuild/Oxc.
|
||||||
|
*/
|
||||||
|
export const browserslistToTargets = (browsers) => {
|
||||||
|
const result = new Map();
|
||||||
|
|
||||||
|
for (const browser of browsers) {
|
||||||
|
// Шаг 1: ['chrome', '109'].
|
||||||
|
let [name, version] = browser.split(' ');
|
||||||
|
// Шаг 2: подмена идентификаторов.
|
||||||
|
name = REPLACES[name] ?? name;
|
||||||
|
// Шаг 3: диапазон → нижняя граница.
|
||||||
|
version = version.includes('-') ? version.slice(0, version.indexOf('-')) : version;
|
||||||
|
// Шаг 4: `18.0` → `18`, но `18.5` не должно трогаться.
|
||||||
|
version = version.endsWith('.0') ? version.slice(0, -2) : version;
|
||||||
|
|
||||||
|
// Шаг 5: валидная версия + поддерживаемый браузер.
|
||||||
|
if (/^\d+(\.\d+)*$/.test(version) && SUPPORTED_TARGETS.has(name)) {
|
||||||
|
// Шаг 6: самая старая версия (последняя в списке) перезатирает предыдущую.
|
||||||
|
result.set(name, version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Шаг 7: собираем без пробела.
|
||||||
|
return [...result].map(([name, version]) => `${name}${version}`);
|
||||||
|
};
|
||||||
14
packages/browserslist-to-targets/package.json
Normal file
14
packages/browserslist-to-targets/package.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "@advdominion/browserslist-to-targets",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"main": "index.js",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://gitea.optiweb.ru/public/frontend.git"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,12 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
|
"@advdominion/browserslist-to-targets@workspace:packages/browserslist-to-targets":
|
||||||
|
version: 0.0.0-use.local
|
||||||
|
resolution: "@advdominion/browserslist-to-targets@workspace:packages/browserslist-to-targets"
|
||||||
|
languageName: unknown
|
||||||
|
linkType: soft
|
||||||
|
|
||||||
"@advdominion/css-var@workspace:packages/css-var":
|
"@advdominion/css-var@workspace:packages/css-var":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@advdominion/css-var@workspace:packages/css-var"
|
resolution: "@advdominion/css-var@workspace:packages/css-var"
|
||||||
|
|||||||
Reference in New Issue
Block a user