Files
frontend/packages/sass-importer/README.md

71 lines
4.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# @advdominion/sass-importer
Кастомный импортёр для [sass-embedded](https://github.com/sass/dart-sass-embedded), который берёт резолв `@use`/`@forward`-импортов на себя и читает файлы через `node:fs`.
## Зачем
В проектах на **Yarn PnP** пакеты лежат не в `node_modules`, а внутри `.zip` по виртуальным путям:
```
.yarn/__virtual__/@example-example-virtual-.../cache/@example-example-....zip/node_modules/@example/example/...
```
`.zip`-путь может открыть только код, читающий файлы через `node:fs` (в нём есть PnP-хуки). А `sass-embedded` читает файлы своим отдельным кодом, `node:fs` не использует, поэтому импорты внутри пакетов не резолвятся. Этот импортёр обходит проблему: он сам превращает импорт в существующий файл (`canonicalize`) и отдаёт его содержимое через `readFileSync` (`load`).
Работает и в `node-modules`-проектах — там `require` без PnP-хуков, но тот же резолв остаётся корректным.
## Установка
```bash
yarn add -D @advdominion/sass-importer
```
## Использование
```js
import { createImporter } from '@advdominion/sass-importer';
const require = createRequire(import.meta.url);
const importer = createImporter(require);
const { css } = compiler.compileString(source, {
importers: [importer],
loadPaths: ['src/styles'],
});
```
Импортёр принимает `require` из `createRequire(import.meta.url)`: в PnP он несёт PnP-хуки, в `node-modules` — обычный `require`. Это позволяет резолвить и пакеты, и их внутренние относительные импорты одинаково надёжно.
## API
### `createImporter(require): Importer`
- `require` — функция резолва (обычно `createRequire(import.meta.url)`), используется для ветки `pkg:`.
- Возвращает объект из двух колбэков для `sass-embedded`: `canonicalize` и `load`.
`canonicalize(url, ctx)` превращает импорт в канонический `file://` URL или возвращает `null` («я не знаю такой файл» — тогда Sass перебирает следующие импортёры/`loadPaths`).
`load(canonicalUrl)` отдаёт содержимое файла и его синтаксис (`syntax: 'scss'`). Если файла нет — бросает `Error: Stylesheet not found: <путь>`.
## Правила резолва
| Приоритет | Вариант | Пример |
| --------- | ------------------ | --------------------------------------- |
| 1 | Точное совпадение | `@use 'variables'``variables` (файл) |
| 2 | Файл с расширением | `@use 'variables'``variables.scss` |
| 3 | Каталог с `_index` | `@use './lib'``./lib/_index.scss` |
| 4 | Каталог с `index` | `@use './lib'``./lib/index.scss` |
Для каталогов берутся `_index` и `index` как с `.scss`, так и с `.css`. Порядок проверок соответствует порядку перебора Sass, поэтому первая найденная запись — приоритетная.
## Виды импортов
- `pkg:@scope/pkg/path/to/file``require.resolve` + резолв кандидата.
- `file:///abs/path` → кандидат по файловому пути.
- относительные (`../../variables`) → склейка с каталогом содержащего файла (берётся из `ctx.containingUrl`), затем резолв кандидата.
- абсолютные (`/...`) и незнакомые схемы (`http:`, `data:`) → отдаёт `null`, резолв остаётся на Sass.
## Лицензия
MIT