Module: HamlToErb

Defined in:
lib/haml_to_erb.rb,
lib/haml_to_erb/version.rb,
lib/haml_to_erb/converter.rb,
lib/haml_to_erb/prism_parser.rb,
lib/haml_to_erb/interpolation.rb,
lib/haml_to_erb/attribute_builder.rb

Overview

HamlToErb - A HAML to ERB converter

Converts HAML templates to ERB format. Designed for migration tools running on trusted source files.

Features:

  • Tags with classes/IDs: %div.class#id
  • Ruby hash attributes: { key: 'value', data: { x: 1 } }
  • HTML attributes: (href="url")
  • Ruby code: = output, - silent
  • Blocks with do |var|
  • Filters: :javascript, :plain, :css, :erb
  • Interpolation: #expression

Usage:

HamlToErb.convert(haml_string)  # Returns ERB string
HamlToErb.convert_file('path/to/file.haml')  # Creates .erb file
HamlToErb.convert_directory('app/views')  # Converts all .haml files

Validation (requires herb gem):

HamlToErb.validate(erb_string)  # Returns { valid: bool, errors: [...] }
HamlToErb.convert_and_validate(haml_string)  # Returns { erb:, valid:, errors: }

Defined Under Namespace

Modules: Interpolation Classes: AttributeBuilder, Converter, PrismParser, ValidationResult

Constant Summary collapse

VERSION =
"0.1.0"

Class Method Summary collapse

Class Method Details

.convert(input) ⇒ String

Convert a HAML string to ERB.

Parameters:

  • input (String) —

    HAML template source

Returns:

  • (String) —

    converted ERB output

Raises:

  • (Haml::SyntaxError) —

    if the input is not valid HAML



66
67
68
# File 'lib/haml_to_erb.rb', line 66

def self.convert(input)
  Converter.new(input).convert
end

.convert_and_validate(input) ⇒ ValidationResult

Convert HAML to ERB and validate the output in one step.

Parameters:

  • input (String) —

    HAML template source

Returns:

Raises:

  • (RuntimeError) —

    if the herb gem is not installed



87
88
89
90
# File 'lib/haml_to_erb.rb', line 87

def self.convert_and_validate(input)
  erb = convert(input)
  validate(erb)
end

.convert_directory(dir_path, delete_originals: false, validate: false, dry_run: false) ⇒ Array<Hash>

Convert all .haml files in a directory tree to ERB.

Parameters:

  • dir_path (String) —

    root directory to search for .haml files

  • delete_originals (Boolean) (defaults to: false) —

    remove .haml files after successful conversion

  • validate (Boolean) (defaults to: false) —

    validate each ERB output with Herb

  • dry_run (Boolean) (defaults to: false) —

    return converted output without writing to disk

Returns:

  • (Array<Hash>) —

    array of result hashes, one per file (see convert_file)



137
138
139
140
141
# File 'lib/haml_to_erb.rb', line 137

def self.convert_directory(dir_path, delete_originals: false, validate: false, dry_run: false)
  Dir.glob(File.join(dir_path, "**/*.haml")).map do |haml_path|
    convert_file(haml_path, delete_original: delete_originals, validate: validate, dry_run: dry_run)
  end
end

.convert_file(haml_path, delete_original: false, validate: false, dry_run: false) ⇒ Hash

Convert a single HAML file to ERB, writing the result alongside the original.

Parameters:

  • haml_path (String) —

    path to the .haml file

  • delete_original (Boolean) (defaults to: false) —

    remove the .haml file after successful conversion

  • validate (Boolean) (defaults to: false) —

    validate the ERB output with Herb

  • dry_run (Boolean) (defaults to: false) —

    return the converted output without writing to disk

Returns:

  • (Hash) —

    result with :path, :errors, and optionally :skipped, :dry_run, :content



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/haml_to_erb.rb', line 99

def self.convert_file(haml_path, delete_original: false, validate: false, dry_run: false)
  erb_path = haml_path.sub(/\.haml\z/, ".erb")

  begin
    content = File.read(haml_path)
    erb = convert(content)
  rescue Errno::ENOENT
    return { path: erb_path, errors: [ { message: "File not found: #{haml_path}" } ], skipped: true }
  rescue Errno::EACCES
    return { path: erb_path, errors: [ { message: "Permission denied: #{haml_path}" } ], skipped: true }
  rescue Haml::SyntaxError => e
    line = e.respond_to?(:line) ? e.line : nil
    return { path: erb_path, errors: [ { message: "HAML syntax error: #{e.message}", line: line } ], skipped: true }
  end

  unless dry_run
    begin
      File.write(erb_path, erb)
      File.delete(haml_path) if delete_original
    rescue Errno::EACCES
      return { path: erb_path, errors: [ { message: "Cannot write: #{erb_path}" } ], skipped: true }
    end
  end

  errors = validate ? self.validate(erb).errors : []
  result = { path: erb_path, errors: errors }
  result[:dry_run] = true if dry_run
  result[:content] = erb if dry_run
  result
end

.herb_available? ⇒ Boolean

Check if the Herb gem is available for validation.

Returns:

  • (Boolean)


146
147
148
149
150
151
# File 'lib/haml_to_erb.rb', line 146

def self.herb_available?
  require "herb"
  true
rescue LoadError
  false
end

.validate(erb) ⇒ ValidationResult

Validate ERB output using the Herb parser.

Parameters:

  • erb (String) —

    ERB string to validate

Returns:

Raises:

  • (RuntimeError) —

    if the herb gem is not installed



75
76
77
78
79
80
# File 'lib/haml_to_erb.rb', line 75

def self.validate(erb)
  require_herb!
  result = Herb.parse(erb)
  errors = result.success? ? [] : result.errors.map { |e| format_herb_error(e) }
  ValidationResult.new(erb: erb, errors: errors)
end