# `Vize.CSS`
[🔗](https://github.com/elixir-volt/vize_ex/blob/v0.17.0/lib/vize/css.ex#L1)

CSS parsing, printing, and AST traversal helpers.

The AST is produced by LightningCSS and represented as Elixir maps, lists,
strings, numbers, booleans, and `nil`. Use `parse_ast/2` to parse CSS,
transform the returned AST with `prewalk/2` or `postwalk/2`, and then use
`print_ast/2` to serialize it back to CSS.

# `ast`

```elixir
@type ast() :: map() | list() | String.t() | number() | boolean() | nil
```

# `ast_result`

```elixir
@type ast_result() :: %{
  ast: map() | nil,
  errors: [String.t()],
  warnings: [String.t()]
}
```

# `css_result`

```elixir
@type css_result() :: %{
  optional(:exports) =&gt; %{optional(String.t()) =&gt; String.t()} | nil,
  code: String.t(),
  css_vars: [String.t()],
  errors: [String.t()],
  warnings: [String.t()]
}
```

# `url_ref`

```elixir
@type url_ref() :: Vize.CSS.URL.t()
```

# `bundle`

```elixir
@spec bundle(
  String.t(),
  keyword()
) :: {:ok, css_result()}
```

Bundle a CSS file and all its `@import` dependencies into a single stylesheet.

Reads the entry file and all imported files from disk, resolving `@import`
rules recursively. The result is a single merged stylesheet with all imports
inlined, wrapped in the appropriate `@media`, `@supports`, and `@layer` rules.

## Options

  * `:minify` — minify the output (default: `false`)
  * `:css_modules` — enable CSS Modules scoping (default: `false`)
  * `:targets` — browser targets for autoprefixing; they take effect only with
    `minify: true`

# `bundle!`

```elixir
@spec bundle!(
  String.t(),
  keyword()
) :: css_result()
```

Like `bundle/2` but raises on errors.

# `collect`

```elixir
@spec collect(ast(), (map() -&gt; {:keep, term()} | :skip)) :: [term()]
```

Collect values from map nodes that match `fun`.

`fun` should return `{:keep, value}` to include a value, or `:skip` to ignore
the node.

# `collect_urls`

```elixir
@spec collect_urls(
  String.t(),
  keyword()
) :: {:ok, [url_ref()]} | {:error, Vize.Error.t()}
```

Collect parser-backed `url()` references from CSS source.

Returns byte offsets for the URL value inside the original source, suitable for
source patching without round-tripping through the serialized CSS AST.

# `collect_urls!`

```elixir
@spec collect_urls!(
  String.t(),
  keyword()
) :: [url_ref()]
```

Like `collect_urls/2` but raises `Vize.Error` on errors.

# `compile`

```elixir
@spec compile(
  String.t(),
  keyword()
) :: {:ok, css_result()}
```

Compile CSS using LightningCSS.

Parses, autoprefixes, and optionally minifies CSS. Also handles Vue scoped CSS
transformation, `v-bind()` extraction, and CSS Modules.

## Options

  * `:minify` — minify the output (default: `false`)
  * `:scoped` — apply Vue scoped CSS transformation (default: `false`)
  * `:scope_id` — scope ID for scoped CSS (e.g. `"data-v-abc123"`)
  * `:filename` — filename for error reporting
  * `:css_modules` — enable CSS Modules scoping (default: `false`)
  * `:targets` — browser targets for autoprefixing, map with optional
    `:chrome`, `:firefox`, `:safari` keys as major version integers. Vize
    applies them while minifying, so they take effect only with `minify: true`

## Examples

    iex> {:ok, result} = Vize.CSS.compile(".foo { color: red }")
    iex> result.code =~ "color"
    true
    iex> result.errors
    []

# `compile!`

```elixir
@spec compile!(
  String.t(),
  keyword()
) :: css_result()
```

Like `compile/2` but raises on errors.

# `compile_sass`

```elixir
@spec compile_sass(
  String.t(),
  keyword()
) :: {:ok, %{code: String.t()}} | {:error, String.t()}
```

Compile Sass or SCSS to CSS using the native Rust `grass` compiler.

## Options

  * `:syntax` — `:scss` (default) or `:sass`
  * `:filename` — source filename, used to resolve relative imports
  * `:load_paths` — additional directories used to resolve imports
  * `:compressed` — emit compressed CSS (default: `false`)

# `compile_sass!`

```elixir
@spec compile_sass!(
  String.t(),
  keyword()
) :: %{code: String.t()}
```

Like `compile_sass/2` but raises on compilation errors.

# `parse_ast`

```elixir
@spec parse_ast(
  String.t(),
  keyword()
) :: {:ok, ast_result()}
```

Parse CSS into a LightningCSS-backed AST represented as Elixir maps and lists.

## Options

  * `:filename` — filename for parser locations and error reporting
  * `:css_modules` — enable CSS Modules parsing (default: `false`)
  * `:custom_media` — enable custom media parsing (default: `false`)

## Examples

    iex> {:ok, result} = Vize.CSS.parse_ast(".foo { background: url('./logo.svg') }")
    iex> is_map(result.ast)
    true
    iex> result.errors
    []

# `parse_ast!`

```elixir
@spec parse_ast!(
  String.t(),
  keyword()
) :: ast_result()
```

Like `parse_ast/2` but raises on errors.

# `postwalk`

```elixir
@spec postwalk(ast(), (map() -&gt; map())) :: ast()
```

Depth-first post-order traversal, like `Macro.postwalk/2`.

The callback receives every map node after its children and must return the
transformed node.

# `postwalk`

```elixir
@spec postwalk(ast(), acc, (map(), acc -&gt; {map(), acc})) :: {ast(), acc}
when acc: term()
```

Depth-first post-order traversal with accumulator, like `Macro.postwalk/3`.

# `prewalk`

```elixir
@spec prewalk(ast(), (map() -&gt; map())) :: ast()
```

Depth-first pre-order traversal, like `Macro.prewalk/2`.

The callback receives every map node before its children and must return the
node to continue traversing.

# `prewalk`

```elixir
@spec prewalk(ast(), acc, (map(), acc -&gt; {map(), acc})) :: {ast(), acc}
when acc: term()
```

Depth-first pre-order traversal with accumulator, like `Macro.prewalk/3`.

# `print_ast`

```elixir
@spec print_ast(
  map(),
  keyword()
) :: {:ok, css_result()}
```

Print CSS from an AST returned by `parse_ast/2`.

## Options

  * `:minify` — minify the output (default: `false`)
  * `:targets` — browser targets for autoprefixing, map with optional
    `:chrome`, `:firefox`, `:safari` keys as major version integers. Vize
    applies them while minifying, so they take effect only with `minify: true`

## Examples

    iex> {:ok, parsed} = Vize.CSS.parse_ast(".foo { color: red }")
    iex> {:ok, printed} = Vize.CSS.print_ast(parsed.ast)
    iex> printed.code =~ "color"
    true

# `print_ast!`

```elixir
@spec print_ast!(
  map(),
  keyword()
) :: css_result()
```

Like `print_ast/2` but raises on errors.

# `rewrite_urls`

Rewrite parser-backed `url()` references in CSS source.

The callback receives each URL string and returns either `:keep` or
`{:rewrite, new_url}`. Rewrites are applied to the original source using byte
ranges reported by the native parser.

# `rewrite_urls`

```elixir
@spec rewrite_urls(String.t(), keyword(), (String.t() -&gt; :keep | {:rewrite, iodata()})) ::
  {:ok, String.t()} | {:error, Vize.Error.t()}
```

# `rewrite_urls!`

Like `rewrite_urls/3` but raises `Vize.Error` on errors.

# `rewrite_urls!`

```elixir
@spec rewrite_urls!(String.t(), keyword(), (String.t() -&gt;
                                        :keep | {:rewrite, iodata()})) ::
  String.t()
```

# `select`

```elixir
@spec select(String.t(), atom(), keyword()) ::
  {:ok, [map()]} | {:error, Vize.Error.t()}
```

Select compact parser events from CSS source by name.

Available selectors:

  * `:urls` — `url()` references with source byte ranges and source locations
  * `:imports` — `@import` references with source byte ranges, source locations,
    and optional `supports` / `media` conditions
  * `:dependencies` — both `url()` and `@import` dependency references with a
    `:kind` field of `:url` or `:import`

## Options

  * `:filename` — filename for parser locations and error reporting
  * `:css_modules` — enable CSS Modules parsing (default: `false`)
  * `:custom_media` — enable custom media parsing (default: `false`)

# `walk`

```elixir
@spec walk(ast(), (map() -&gt; any())) :: :ok
```

Traverse the AST in pre-order and call `fun` for every map node.

Returns `:ok`. Use `prewalk/2` or `postwalk/2` when you need to transform
the AST.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
