Elixir bindings for the Vize 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"
trueVapor 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
Summary
Functions
Bundle a CSS file and all its @import dependencies into a single stylesheet.
Like bundle_css/2 but raises on errors.
Compile CSS using LightningCSS.
Like compile_css/2 but raises on errors.
Compile a Vue Single File Component to JavaScript + CSS.
Like compile_sfc/2 but raises on errors.
Compile a Vue template for server-side rendering.
Like compile_ssr/1 but raises on errors.
Compile a Vue template string to a render function.
Like compile_template/2 but raises on errors.
Compile a Vue template to Vapor mode JavaScript.
Like compile_vapor/2 but raises on errors.
Generate a TypeScript declaration file (.d.ts) from a Vue SFC.
Like generate_dts/2 but raises on errors.
Lint a Vue SFC source string.
Parse a Vue Single File Component into its constituent blocks.
Like parse_sfc/1 but raises on errors.
Get the Vapor mode intermediate representation as Elixir maps.
Like vapor_ir/1 but raises on errors.
Compile a Vue template into a statics/slots split ready for LiveView %Rendered{}.
Types
@type dts_result() :: %{dts: String.t()}
@type ir_result() :: %{ templates: [String.t()], components: [String.t()], directives: [String.t()], block: map(), element_template_map: [{non_neg_integer(), non_neg_integer()}] }
@type macro_artifact() :: %{ :kind => String.t(), :name => String.t(), :source => String.t(), :content => String.t(), :start => non_neg_integer(), :end => non_neg_integer(), optional(:code) => String.t() }
Functions
@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
@spec bundle_css!( String.t(), keyword() ) :: css_result()
Like bundle_css/2 but raises on errors.
@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:exportsmap of original → hashed names.:targets— browser targets for autoprefixing, map with optional:chrome,:firefox,:safarikeys 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
@spec compile_css!( String.t(), keyword() ) :: css_result()
Like compile_css/2 but raises on errors.
@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
[]
@spec compile_sfc!( String.t(), keyword() ) :: sfc_result()
Like compile_sfc/2 but raises on errors.
@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
@spec compile_ssr!(String.t()) :: ssr_result()
Like compile_ssr/1 but raises on errors.
@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
@spec compile_template!( String.t(), keyword() ) :: template_result()
Like compile_template/2 but raises on errors.
@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
@spec compile_vapor!( String.t(), keyword() ) :: vapor_result()
Like compile_vapor/2 but raises on errors.
@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
@spec generate_dts!( String.t(), keyword() ) :: dts_result()
Like generate_dts/2 but raises on errors.
@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 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
Like parse_sfc/1 but raises on errors.
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
Like vapor_ir/1 but raises on errors.
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:kindand 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.