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

Elixir bindings for the [Vize](https://vizejs.dev) Vue.js toolchain.

Compile, lint, and analyze Vue Single File Components at native speed
via Rust NIFs. Includes Vapor mode IR for BEAM-native SSR.

    iex> {:ok, result} = Vize.compile_sfc("""
    ...> <template><div>{{ msg }}</div></template>
    ...> <script setup>
    ...> const msg = 'hello'
    ...> </script>
    ...> """)
    iex> result.code =~ "msg"
    true

## Vapor IR

The `vapor_ir/1` function exposes Vue's Vapor mode intermediate
representation as Elixir maps — enabling BEAM-native SSR without
executing JavaScript:

    iex> {:ok, ir} = Vize.vapor_ir("<div>{{ msg }}</div>")
    iex> [template] = ir.templates
    iex> template =~ "<div>"
    true

# `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()]
}
```

# `diagnostic`

```elixir
@type diagnostic() :: %{message: String.t(), name: String.t() | nil}
```

# `dts_result`

```elixir
@type dts_result() :: %{dts: String.t()}
```

# `ir_result`

```elixir
@type ir_result() :: %{
  templates: [String.t()],
  components: [String.t()],
  directives: [String.t()],
  block: map(),
  element_template_map: [{non_neg_integer(), non_neg_integer()}]
}
```

# `macro_artifact`

```elixir
@type macro_artifact() :: %{
  :kind =&gt; String.t(),
  :name =&gt; String.t(),
  :source =&gt; String.t(),
  :content =&gt; String.t(),
  :start =&gt; non_neg_integer(),
  :end =&gt; non_neg_integer(),
  optional(:code) =&gt; String.t()
}
```

# `sfc_result`

```elixir
@type sfc_result() :: %{
  code: String.t(),
  css: String.t() | nil,
  errors: [map()],
  warnings: [map()],
  template_hash: String.t() | nil,
  style_hash: String.t() | nil,
  script_hash: String.t() | nil,
  macro_artifacts: [macro_artifact()]
}
```

# `ssr_result`

```elixir
@type ssr_result() :: %{code: String.t(), preamble: String.t()}
```

# `template_result`

```elixir
@type template_result() :: %{
  code: String.t(),
  preamble: String.t(),
  helpers: [String.t()]
}
```

# `vapor_result`

```elixir
@type vapor_result() :: %{code: String.t(), templates: [String.t()]}
```

# `bundle_css`

```elixir
@spec bundle_css(
  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

## Examples

    {:ok, result} = Vize.bundle_css("assets/css/app.css")
    result.code  #=> merged CSS with all @imports inlined

# `bundle_css!`

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

Like `bundle_css/2` but raises on errors.

# `compile_css`

```elixir
@spec compile_css(
  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`).
    When enabled, class names, IDs, keyframes, and other identifiers are
    scoped, and the result includes an `:exports` map of original → hashed names.
  * `:targets` — browser targets for autoprefixing, map with optional
    `:chrome`, `:firefox`, `:safari` keys as major version integers

## Examples

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

    iex> {:ok, result} = Vize.compile_css(".btn { color: red }", css_modules: true, filename: "btn.module.css")
    iex> is_map(result.exports)
    true

# `compile_css!`

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

Like `compile_css/2` but raises on errors.

# `compile_sfc`

```elixir
@spec compile_sfc(
  String.t(),
  keyword()
) :: {:ok, sfc_result()} | {:error, String.t()}
```

Compile a Vue Single File Component to JavaScript + CSS.

Handles `<template>`, `<script>`, `<script setup>`, and `<style>` blocks.

## Options

  * `:vapor` — compile in Vapor mode (default: `false`)
  * `:ssr` — compile for server-side rendering (default: `false`)
  * `:filename` — SFC filename for scope ID generation and source maps (e.g. `"App.vue"`)
  * `:scope_id` — explicit scope ID for scoped CSS (default: auto-generated from filename)
  * `:custom_renderer` — treat lowercase non-HTML tags as renderer-native
    elements instead of Vue components (default: `false`)
  * `:strip_types` — strip TypeScript type annotations from the output
    using OXC, returning plain JavaScript (default: `false`)

## Examples

    iex> {:ok, result} = Vize.compile_sfc("""
    ...> <template><button @click="count++">{{ count }}</button></template>
    ...> <script setup>
    ...> import { ref } from 'vue'
    ...> const count = ref(0)
    ...> </script>
    ...> """)
    iex> result.code =~ "count"
    true
    iex> result.errors
    []

# `compile_sfc!`

```elixir
@spec compile_sfc!(
  String.t(),
  keyword()
) :: sfc_result()
```

Like `compile_sfc/2` but raises on errors.

# `compile_ssr`

```elixir
@spec compile_ssr(String.t()) :: {:ok, ssr_result()} | {:error, [String.t()]}
```

Compile a Vue template for server-side rendering.

Generates JavaScript with `_push()` calls that produce HTML strings.
The output is meant to be executed in a JS runtime (e.g. QuickBEAM).

## Examples

    iex> {:ok, result} = Vize.compile_ssr("<div>{{ msg }}</div>")
    iex> result.code =~ "_push"
    true

# `compile_ssr!`

```elixir
@spec compile_ssr!(String.t()) :: ssr_result()
```

Like `compile_ssr/1` but raises on errors.

# `compile_template`

```elixir
@spec compile_template(
  String.t(),
  keyword()
) :: {:ok, template_result()} | {:error, [String.t()]}
```

Compile a Vue template string to a render function.

This compiles just the template (not a full SFC). Useful for
on-the-fly template compilation.

## Options

  * `:mode` — output mode, `"function"` (default) or `"module"`
  * `:ssr` — compile for SSR (default: `false`)

## Examples

    iex> {:ok, result} = Vize.compile_template("<div>{{ msg }}</div>")
    iex> result.code =~ "msg"
    true

# `compile_template!`

```elixir
@spec compile_template!(
  String.t(),
  keyword()
) :: template_result()
```

Like `compile_template/2` but raises on errors.

# `compile_vapor`

```elixir
@spec compile_vapor(
  String.t(),
  keyword()
) :: {:ok, vapor_result()} | {:error, [String.t()]}
```

Compile a Vue template to Vapor mode JavaScript.

Vapor mode generates fine-grained reactive code that manipulates
the DOM directly, without a virtual DOM.

## Options

  * `:ssr` — compile for SSR (default: `false`)

## Examples

    iex> {:ok, result} = Vize.compile_vapor("<div>{{ msg }}</div>")
    iex> result.code =~ "template"
    true
    iex> length(result.templates) > 0
    true

# `compile_vapor!`

```elixir
@spec compile_vapor!(
  String.t(),
  keyword()
) :: vapor_result()
```

Like `compile_vapor/2` but raises on errors.

# `generate_dts`

```elixir
@spec generate_dts(
  String.t(),
  keyword()
) :: {:ok, dts_result()} | {:error, String.t()}
```

Generate a TypeScript declaration file (`.d.ts`) from a Vue SFC.

Analyzes the SFC's script blocks and produces a lightweight type
surface for component consumers — including prop types, emit signatures,
exposed bindings, and slot definitions.

## Options

  * `:filename` — SFC filename for diagnostics (default: `"component.vue"`)

## Examples

    iex> {:ok, result} = Vize.generate_dts("<script setup>const msg = 1</script>")
    iex> is_binary(result.dts)
    true

# `generate_dts!`

```elixir
@spec generate_dts!(
  String.t(),
  keyword()
) :: dts_result()
```

Like `generate_dts/2` but raises on errors.

# `lint`

```elixir
@spec lint(String.t(), String.t()) :: {:ok, [diagnostic()]}
```

Lint a Vue SFC source string.

Returns a list of diagnostics with `:message` and optionally `:name`
(the rule name).

## Examples

    iex> {:ok, diagnostics} = Vize.lint("<template><img></template>", "test.vue")
    iex> is_list(diagnostics)
    true

# `parse_sfc`

```elixir
@spec parse_sfc(String.t()) :: {:ok, map()} | {:error, String.t()}
```

Parse a Vue Single File Component into its constituent blocks.

Returns the SFC descriptor with template, script, script_setup, styles,
and custom_blocks — without compiling.

## Examples

    iex> {:ok, descriptor} = Vize.parse_sfc("""
    ...> <template><div>hello</div></template>
    ...> <script setup>const x = 1</script>
    ...> <style scoped>.red { color: red }</style>
    ...> """)
    iex> descriptor.template.content =~ "hello"
    true
    iex> descriptor.script_setup.setup
    true
    iex> hd(descriptor.styles).scoped
    true

# `parse_sfc!`

```elixir
@spec parse_sfc!(String.t()) :: map()
```

Like `parse_sfc/1` but raises on errors.

# `vapor_ir`

```elixir
@spec vapor_ir(String.t()) :: {:ok, ir_result()} | {:error, [String.t()]}
```

Get the Vapor mode intermediate representation as Elixir maps.

This is the key function for BEAM-native SSR. Instead of generating
JavaScript, it returns the structured IR that describes how to render
the template — enabling a pure Elixir renderer.

The IR contains:

  * `:templates` — static HTML template strings
  * `:components` — component names used in the template
  * `:directives` — directive names used in the template
  * `:block` — the root block with operations, effects, and returns
  * `:element_template_map` — list of `{element_id, template_index}` tuples

Expressions are either plain strings (dynamic) or `{:static, value}`
tuples (compile-time constants).

Each operation has a `:kind` field indicating its type:

  * `:set_prop` — set an attribute/property on an element
  * `:set_text` — set text content (interpolation)
  * `:set_event` — bind an event handler
  * `:set_html` — set innerHTML (v-html)
  * `:if_node` — v-if/v-else-if/v-else chain
  * `:for_node` — v-for loop
  * `:create_component` — child component
  * `:child_ref` / `:next_ref` — DOM traversal helpers

## Examples

    iex> {:ok, ir} = Vize.vapor_ir("<div :class=\"cls\">{{ msg }}</div>")
    iex> [_template] = ir.templates
    iex> ir.block.effects |> List.flatten() |> Enum.any?(&match?(%{kind: :set_text}, &1))
    true

# `vapor_ir!`

```elixir
@spec vapor_ir!(String.t()) :: ir_result()
```

Like `vapor_ir/1` but raises on errors.

# `vapor_split`

```elixir
@spec vapor_split(String.t()) :: {:ok, map()} | {:error, [String.t()]}
```

Compile a Vue template into a statics/slots split ready for LiveView `%Rendered{}`.

Returns `{:ok, split}` where `split` has:
- `"statics"` — list of static HTML strings (interleaved between dynamic slots)
- `"slots"` — ordered list of slot descriptors, each with `:kind` and values/sub-IR
- `:templates` — raw template strings (for sub-block rendering)
- `:element_template_map` — element ID → template index mapping

The statics + slots can be directly assembled into a `%Phoenix.LiveView.Rendered{}`
struct by evaluating each slot against assigns.

# `vapor_split!`

```elixir
@spec vapor_split!(String.t()) :: map()
```

---

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