Class: Rhales::TemplateEngine

Inherits:
Object
  • Object
show all
Defined in:
lib/rhales/template_engine.rb

Overview

Rhales - Ruby Handlebars-style template engine

Modern AST-based template engine that supports both simple template strings and full .rue files. Uses RueFormatParser for parsing with proper nested structure handling and block statement support.

Features:

  • Dual-mode operation: simple templates and .rue files

  • Full AST parsing eliminates regex-based vulnerabilities

  • Proper nested block handling with accurate error reporting

  • XSS protection through HTML escaping by default

  • Handlebars-compatible syntax with Ruby idioms

Supported syntax:

  • {variable} - Variable interpolation with HTML escaping

  • {{variable}} - Raw variable interpolation (no escaping)

  • condition} … {else} … {/if} - Conditionals with else

  • condition} … {/unless} - Negated conditionals

  • items} … {/each} - Iteration with context

  • partial_name} - Partial inclusion

Defined Under Namespace

Classes: BlockNotFoundError, EachContext, PartialNotFoundError, RenderError, UndefinedVariableError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(template_content, context, partial_resolver: nil) ⇒ TemplateEngine

Returns a new instance of TemplateEngine.



37
38
39
40
41
42
# File 'lib/rhales/template_engine.rb', line 37

def initialize(template_content, context, partial_resolver: nil)
  @template_content = template_content
  @context          = context
  @partial_resolver = partial_resolver
  @parser           = nil
end

Instance Attribute Details

#contextObject (readonly)

Returns the value of attribute context.



35
36
37
# File 'lib/rhales/template_engine.rb', line 35

def context
  @context
end

#parserObject (readonly)

Returns the value of attribute parser.



35
36
37
# File 'lib/rhales/template_engine.rb', line 35

def parser
  @parser
end

#partial_resolverObject (readonly)

Returns the value of attribute partial_resolver.



35
36
37
# File 'lib/rhales/template_engine.rb', line 35

def partial_resolver
  @partial_resolver
end

#template_contentObject (readonly)

Returns the value of attribute template_content.



35
36
37
# File 'lib/rhales/template_engine.rb', line 35

def template_content
  @template_content
end

Class Method Details

.file_partial_resolver(templates_dir) ⇒ Object

Create partial resolver that loads .rue files from a directory



338
339
340
341
342
343
344
345
346
347
348
349
350
# File 'lib/rhales/template_engine.rb', line 338

def file_partial_resolver(templates_dir)
  proc do |partial_name|
    partial_path = File.join(templates_dir, "#{partial_name}.rue")

    if File.exist?(partial_path)
      # Load and parse the partial .rue file
      document = RueDocument.parse_file(partial_path)
      document.section('template')
    else
      nil
    end
  end
end

.render(template_content, context, partial_resolver: nil) ⇒ Object

Render template with context and optional partial resolver



333
334
335
# File 'lib/rhales/template_engine.rb', line 333

def render(template_content, context, partial_resolver: nil)
  new(template_content, context, partial_resolver: partial_resolver).render
end

Instance Method Details

#data_attributesObject

Access all data attributes from parsed .rue file



84
85
86
# File 'lib/rhales/template_engine.rb', line 84

def data_attributes
  @parser&.data_attributes || {}
end

#partialsObject

Get all partials used in the template



94
95
96
# File 'lib/rhales/template_engine.rb', line 94

def partials
  @parser&.partials || []
end

#renderObject



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/rhales/template_engine.rb', line 44

def render
  # Check if this is a simple template or a full .rue file
  if simple_template?
    # Use HandlebarsParser for simple templates
    parser = HandlebarsParser.new(@template_content)
    parser.parse!
    render_content_nodes(parser.ast.children)
  else
    # Use RueDocument for .rue files
    @parser = RueDocument.new(@template_content)
    @parser.parse!

    # Get template section via RueDocument
    template_content = @parser.section('template')
    raise RenderError, 'Missing template section' unless template_content

    # Render the template section as a simple template
    render_template_string(template_content)
  end
rescue ::Rhales::ParseError => ex
  # Parse errors already have good error messages with location
  raise RenderError, "Template parsing failed: #{ex.message}"
rescue ::Rhales::ValidationError => ex
  # Validation errors from RueDocument
  raise RenderError, "Template validation failed: #{ex.message}"
rescue StandardError => ex
  raise RenderError, "Template rendering failed: #{ex.message}"
end

#schema_pathObject

Access schema path from parsed .rue file



79
80
81
# File 'lib/rhales/template_engine.rb', line 79

def schema_path
  @parser&.schema_path
end

#template_variablesObject

Get template variables used in the template



89
90
91
# File 'lib/rhales/template_engine.rb', line 89

def template_variables
  @parser&.template_variables || []
end

#window_attributeObject

Access window attribute from parsed .rue file



74
75
76
# File 'lib/rhales/template_engine.rb', line 74

def window_attribute
  @parser&.window_attribute
end