Extending Sheath

Conditional Static Analysis

Sheath follows Blade conditions to determine which markup can appear together when a template renders. This helps rules distinguish a real path-specific problem from markup that only looks incomplete when individual source lines are read in isolation. The analysis does not run application code.

#Conditions and Branches

Core rules correlate simple $flag, !$flag, and @unless($flag) predicates across separate blocks. They also account for nested conditions, loops, @forelse, switch branches, @break, and @continue when deciding whether two pieces of markup can appear on the same rendered path.

Unknown relationships remain unknown. A rule only treats a requirement as met when the source provides enough information for that rule to establish it. This is why two similar templates can produce different results when one uses a literal or repeated predicate and the other depends on an arbitrary expression.

#Attribute Resolution

Attribute order matters because Blade and HTML do not resolve every attribute source the same way.

  • HTML attributes use the first effective value. A dynamic attribute provider before a known attribute can make the result unknown; the same provider after the known attribute cannot replace it.
  • Component attribute data uses last-write behavior when a rule analyzes the compiled component values.
  • Sheath understands known producers such as @class, @style, and Blade's boolean attribute directives. Non-attribute directives such as @csrf and @method do not satisfy an attribute requirement.
  • Targeted Alpine and Livewire bindings affect only their named attribute. For example, x-bind:aria-label can provide a dynamic accessible name, while x-bind:class cannot.
  • A non-empty Alpine object binding such as x-bind="bindings" can provide arbitrary attributes, so Sheath keeps the affected values unknown.

#Rendered Content and Captures

Non-empty x-text, x-html, and wire:text expressions can provide rendered text. Other reactive directives do not become content or an accessible name merely because they can change or reveal an element.

Non-output captures such as @push, @prepend, and a @section that is not closed with @show do not render at their definition site. A @section ... @show block does render in place. Sheath preserves that distinction when a rule checks ancestry or source order.

#Form Submission

A durable wire:submit listener or Alpine submit listener with .prevent replaces the browser's native form submission. .once, .passive, .outside, and .away do not provide the same guarantee, so form-method and CSRF rules do not treat them as equivalent.

#Autofix Safety

Conditional findings do not always have an automatic fix. Sheath offers a safe fix only when the resulting value is valid on every path changed by that edit. Use --dangerous only for fixes whose documented behavior matches the change you intend. See Automatic Fixing for the fix workflow.