Class: JsxRosetta::Backend::Phlex
- Defined in:
- lib/jsx_rosetta/backend/phlex.rb
Overview
Emits a Phlex 2.x view class (one Ruby file per component) from an IR::Component. Single-file output by design — the JSX ‘<h1>…` template lives as Ruby inside `view_template`, not in a sibling .erb. When the source uses `onClick`/`onChange` etc., a sibling Stimulus controller `_controller.js` is emitted alongside (same convention as the ViewComponent backend).
Naming strategies (mutually exclusive):
default class FlashyHeader < Phlex::HTML
suffix: "Component" class FlashyHeaderComponent < Phlex::HTML
namespace: "Components" module Components
class FlashyHeader < Phlex::HTML
Hyphenated attributes (‘data-testid`, `aria-label`, etc.) emit as string-keyed hash entries inside a splat — `**{ “data-testid” => @x }` — since Ruby kwargs can’t carry hyphens. Snake_case-friendly attrs emit as regular keyword arguments.
Defined Under Namespace
Classes: EventDescriptor
Constant Summary collapse
- DEFAULT_SLOT_NAME =
"children"- DEFAULT_SUFFIX =
"Component"- PHLEX_BASE_CLASS =
"Phlex::HTML"- VALID_IDENTIFIER =
/\A[a-z_][a-z0-9_]*\z/i- VOID_ELEMENTS =
%w[area base br col embed hr img input link meta param source track wbr].freeze
Instance Method Summary collapse
- #emit(component) ⇒ Object
-
#initialize(suffix: nil, namespace: nil) ⇒ Phlex
constructor
A new instance of Phlex.
Constructor Details
#initialize(suffix: nil, namespace: nil) ⇒ Phlex
Returns a new instance of Phlex.
38 39 40 41 42 43 44 |
# File 'lib/jsx_rosetta/backend/phlex.rb', line 38 def initialize(suffix: nil, namespace: nil) super() raise ArgumentError, "Phlex backend: pass either suffix: or namespace:, not both" if suffix && namespace @suffix = suffix.is_a?(String) ? suffix : (DEFAULT_SUFFIX if suffix == true) @namespace = namespace end |
Instance Method Details
#emit(component) ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/jsx_rosetta/backend/phlex.rb', line 46 def emit(component) prop_names = component.props.map(&:name) prop_names << component.rest_prop_name if component.rest_prop_name translator = ViewComponent::ExpressionTranslator.new( prop_names: prop_names, local_binding_names: component.local_binding_names ) @stimulus_identifier = component.stimulus_methods.any? ? stimulus_identifier(component) : nil @lambda_methods = [] @lambda_method_counts = {} files = [File.new(path: ruby_path(component), contents: render_ruby_class(component, translator))] if component.stimulus_methods.any? files << File.new( path: stimulus_path(component), contents: render_stimulus_controller_js(component) ) end files end |