# @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