Class: JekyllImgFlow::Parser
- Inherits:
-
Object
- Object
- JekyllImgFlow::Parser
- Defined in:
- lib/jekyll-imgflow/parser.rb
Overview
Central parser for all ImgFlow markup (tags, presets, etc.) Optimized version with reduced duplication and complexity
Constant Summary collapse
- OPERATION_PARAMS =
Define valid operation parameters and attribute types
%i[width height ratio aspect_ratio quality format formats optimize level watermark opacity position keep preset].freeze
- HTML_ATTRIBUTES =
%i[alt class title loading link modal].freeze
- SIMPLE_OPERATIONS =
Simple operation mappings for single-parameter operations
{ quality: ->(val) { { type: :quality, params: { quality: val } } }, watermark: ->(val) { { type: :watermark, params: { text: val } } }, opacity: ->(val) { { type: :alpha_opacity, params: { opacity: val } } } }.freeze
Class Method Summary collapse
- .add_crop_resize_operations(operations, opts) ⇒ Object
- .add_format_operation(operations, opts) ⇒ Object
- .add_optimize_operation(operations, opts) ⇒ Object
- .add_simple_operations(operations, opts) ⇒ Object
- .build_error_response(raw_options, error_message) ⇒ Object
- .build_success_response(image_path, operations, html_attributes, raw_options) ⇒ Object
- .clean_and_convert_value(value, options = {}) ⇒ Object
- .convert_numeric_value(value) ⇒ Object
-
.convert_operations_array(operations_array) ⇒ Object
Convert operations array from TagScanner to structured hash.
- .detect_operations(options) ⇒ Object
- .extract_html_attributes(options) ⇒ Object
- .extract_image_path(options, markup) ⇒ Object
- .parse(markup, _context = nil) ⇒ Object
- .parse_key_value_format(markup, options) ⇒ Object
- .parse_key_value_pairs(pairs, separator, options = {}) ⇒ Object
- .parse_markup_to_hash(markup) ⇒ Object
- .parse_positional_format(markup, options) ⇒ Object
- .validate_structured_data(data) ⇒ Object
Class Method Details
.add_crop_resize_operations(operations, opts) ⇒ Object
121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/jekyll-imgflow/parser.rb', line 121 def self.add_crop_resize_operations(operations, opts) has_crop = opts[:ratio] || opts[:aspect_ratio] has_resize = opts[:width] || opts[:height] crop_params = opts.slice(:ratio, :aspect_ratio, :keep, :position) if has_crop && has_resize operations << { type: :crop, params: crop_params } operations << { type: :resize, params: opts.except(:ratio, :aspect_ratio, :keep, :position) } elsif has_crop operations << { type: :crop, params: crop_params } elsif has_resize operations << { type: :resize, params: opts } end end |
.add_format_operation(operations, opts) ⇒ Object
142 143 144 145 146 147 148 149 150 151 |
# File 'lib/jekyll-imgflow/parser.rb', line 142 def self.add_format_operation(operations, opts) return unless opts[:format] || opts[:formats] format_value = opts[:format] || opts[:formats] operations << if format_value.is_a?(Array) { type: :format, params: { formats: format_value } } else { type: :format, params: { format: format_value } } end end |
.add_optimize_operation(operations, opts) ⇒ Object
153 154 155 156 157 158 |
# File 'lib/jekyll-imgflow/parser.rb', line 153 def self.add_optimize_operation(operations, opts) return unless opts[:optimize] || opts[:level] operations << { type: :optimize, params: { level: opts[:level] || :medium } } end |
.add_simple_operations(operations, opts) ⇒ Object
136 137 138 139 140 |
# File 'lib/jekyll-imgflow/parser.rb', line 136 def self.add_simple_operations(operations, opts) SIMPLE_OPERATIONS.each do |key, builder| operations << builder.call(opts[key]) if opts[key] end end |
.build_error_response(raw_options, error_message) ⇒ Object
182 183 184 185 186 187 188 189 190 191 |
# File 'lib/jekyll-imgflow/parser.rb', line 182 def self.build_error_response(, ) { image_path: nil, operations: [], html_attributes: {}, raw_options: , preset: nil, error: } end |
.build_success_response(image_path, operations, html_attributes, raw_options) ⇒ Object
193 194 195 196 197 198 199 200 201 |
# File 'lib/jekyll-imgflow/parser.rb', line 193 def self.build_success_response(image_path, operations, html_attributes, ) { image_path: image_path, operations: operations, html_attributes: html_attributes, raw_options: , preset: [:preset] } end |
.clean_and_convert_value(value, options = {}) ⇒ Object
81 82 83 84 85 86 87 88 89 |
# File 'lib/jekyll-imgflow/parser.rb', line 81 def self.clean_and_convert_value(value, = {}) value = value.tr("'\"", "") value = convert_numeric_value(value) # Handle comma-separated arrays value = value.split(",").map(&:strip) if [:handle_arrays] && value.is_a?(String) && value.include?(",") value end |
.convert_numeric_value(value) ⇒ Object
91 92 93 94 95 96 |
# File 'lib/jekyll-imgflow/parser.rb', line 91 def self.convert_numeric_value(value) return value.to_i if value.match?(/^\d+$/) return value.to_f if value.match?(/^\d+\.\d+$/) value end |
.convert_operations_array(operations_array) ⇒ Object
Convert operations array from TagScanner to structured hash
173 174 175 176 177 178 179 180 |
# File 'lib/jekyll-imgflow/parser.rb', line 173 def self.convert_operations_array(operations_array) operations_array.each_with_object({}) do |op_str, hash| next unless op_str.include?(":") key, value = op_str.split(":", 2) hash[key.strip.to_sym] = clean_and_convert_value(value.strip, handle_arrays: true) end end |
.detect_operations(options) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/jekyll-imgflow/parser.rb', line 109 def self.detect_operations() operations = [] = .slice(*OPERATION_PARAMS) add_crop_resize_operations(operations, ) add_simple_operations(operations, ) add_format_operation(operations, ) add_optimize_operation(operations, ) operations end |
.extract_html_attributes(options) ⇒ Object
160 161 162 |
# File 'lib/jekyll-imgflow/parser.rb', line 160 def self.extract_html_attributes() .slice(*HTML_ATTRIBUTES) end |
.extract_image_path(options, markup) ⇒ Object
164 165 166 167 168 169 170 |
# File 'lib/jekyll-imgflow/parser.rb', line 164 def self.extract_image_path(, markup) return [:image_path] if [:image_path] return if markup.strip.empty? # Extract first word (before space or =) markup.split(/[\s=]/, 2).first&.strip end |
.parse(markup, _context = nil) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/jekyll-imgflow/parser.rb', line 21 def self.parse(markup, _context = nil) # For KISS architecture: expect structured data from TagScanner return validate_structured_data(markup) if markup.is_a?(Hash) && markup.key?(:image_path) # Parse simple markup (backward compatibility) = parse_markup_to_hash(markup) operations = detect_operations() html_attributes = extract_html_attributes() image_path = extract_image_path(, markup) # Early return if no image path return build_error_response(, "No image path found in markup") unless image_path # File validation handled by PathResolver when resolving paths build_success_response(image_path, operations, html_attributes, ) end |
.parse_key_value_format(markup, options) ⇒ Object
51 52 53 |
# File 'lib/jekyll-imgflow/parser.rb', line 51 def self.parse_key_value_format(markup, ) parse_key_value_pairs(markup.split, "=", result: , handle_arrays: false) end |
.parse_key_value_pairs(pairs, separator, options = {}) ⇒ Object
70 71 72 73 74 75 76 77 78 79 |
# File 'lib/jekyll-imgflow/parser.rb', line 70 def self.parse_key_value_pairs(pairs, separator, = {}) pairs.each do |pair| if pair.include?(separator) key, value = pair.split(separator, 2) [:result][key.to_sym] = clean_and_convert_value(value, ) elsif [:image_path_handler] [:image_path_handler].call(pair, [:result]) end end end |
.parse_markup_to_hash(markup) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/jekyll-imgflow/parser.rb', line 38 def self.parse_markup_to_hash(markup) = {} # Handle different markup formats if markup.include?("=") parse_key_value_format(markup, ) else parse_positional_format(markup, ) end end |
.parse_positional_format(markup, options) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/jekyll-imgflow/parser.rb', line 55 def self.parse_positional_format(markup, ) # Use Shellwords for proper quote handling parts = Shellwords.split(markup) parse_key_value_pairs( parts, ":", result: , handle_arrays: true, image_path_handler: lambda { |part, result| result[:image_path] = part unless result[:image_path] } ) end |
.validate_structured_data(data) ⇒ Object
98 99 100 101 102 103 104 105 106 107 |
# File 'lib/jekyll-imgflow/parser.rb', line 98 def self.validate_structured_data(data) image_path = data[:image_path] operations = data[:operations] || {} return build_error_response(data, "No image path found in structured data") unless image_path # Operations validation handled by Tags - Parser only parses structure # File validation handled by PathResolver when resolving paths build_success_response(image_path, operations, data[:html_attributes] || {}, data) end |