|
# SiRuMeT - Simple Ruby Merge Tags Parser |
|
|
|
## Code |
|
def parse_merge_tags(text, params) |
|
pattern = { |
|
placeholder: /(\*\|(?:MC:)?([A-Za-z0-9_]+)\|\*)/, |
|
condition: %r{ |
|
( |
|
\*\|IF: |
|
([A-Za-z0-9_]+) # match[1] 2nd Capturing Group - merge_tag |
|
(?: |
|
[\s]* |
|
(=|!=|>=|<=|<|>) # match[2] 3rd Capturing Group - operation |
|
[\s]* |
|
([^\*]+?) # match[3] 4th Capturing Group - value |
|
)? |
|
\|\* |
|
(?: |
|
(?: |
|
([^\*]*) # match[4] 5th Capturing Group - consequent |
|
\*\|ELSE:\|\* |
|
([^\*]*) # match[5] 6th Capturing Group - alternative |
|
) |
|
| |
|
([^\*]*) # match[6] 7th Capturing Group - single_consequent |
|
) |
|
\*\|END:IF\|\* |
|
) # match[0] 1st Capturing Group - capture_text |
|
}x |
|
} |
|
|
|
# Scan for placeholder tags |
|
text.scan(pattern[:placeholder]).each do |match| |
|
value = params[match[1]] |
|
text = if value.nil? |
|
text.gsub(match[0], '') |
|
else |
|
text.gsub(match[0], value) |
|
end |
|
end |
|
|
|
# Scan for conditions |
|
text.scan(pattern[:condition]).each do |match| |
|
text = perform_match text, match, params |
|
end |
|
text |
|
end |
|
|
|
def perform_match(text, match, params) |
|
value = params[match[1]] |
|
match[2] = '==' if match[2] == '=' |
|
|
|
condition_respected = |
|
if match[2].nil? |
|
# Condition has no operator |
|
# Test only if value exists |
|
!value.nil? |
|
elsif ['>=', '<=', '<', '>'].include?(match[2]) |
|
# Numerical comparaison |
|
!value.nil? && value.to_i.send(match[2], match[3].to_i) |
|
else |
|
# String comparaison |
|
!value.nil? && value.to_s.send(match[2], match[3].to_s) |
|
end |
|
|
|
has_else_statement = match[6].nil? |
|
|
|
# Replace the occurrences in the text |
|
text = replace_text_occurrences(text, has_else_statement, condition_respected, match) |
|
|
|
# Remove multiple line breaks |
|
text.gsub(/\n\s*\n\s*\n/, "\n\n").strip |
|
end |
|
|
|
# Replace the occurrences in the text |
|
def replace_text_occurrences(text, has_else_statement, condition_respected, match) |
|
if has_else_statement && condition_respected |
|
text.gsub(match[0], match[4]) |
|
elsif has_else_statement && !condition_respected |
|
text.gsub(match[0], match[5]) |
|
elsif !has_else_statement && condition_respected |
|
text.gsub(match[0], match[6]) |
|
else |
|
text.gsub(match[0], '') |
|
end |
|
end |
|
|
|
## Example |
|
message = <<-eos |
|
***|MC:SUBJECT|*** |
|
|
|
Hello *|IF:FNAME|* |
|
*|FNAME|*, |
|
*|ELSE:|* |
|
Friend, |
|
*|END:IF|* |
|
|
|
*|IF:MC_LANGUAGE=es|* |
|
Spanish content here. |
|
*|ELSE:|* |
|
Display English content for everyone else. |
|
*|END:IF|* |
|
|
|
*|IF:TRANSACTIONS >= 10|* |
|
Enjoy this 20% off coupon! *|COUPON20|* |
|
*|ELSE:|* |
|
Enjoy this 10% off coupon! *|COUPON10|* |
|
*|END:IF|* |
|
eos |
|
|
|
params = { |
|
'SUBJECT' => 'SiRuMeT', |
|
'FNAME' => 'John Doe', |
|
'MC_LANGUAGE' => 'es', |
|
'TRANSACTIONS' => 15 |
|
} |
|
|
|
puts parse_merge_tags(message, params) |
|
|
|
## Result |
|
# => "**SiRuMeT**\n\nHello \n John Doe,\n\nSpanish content here.\n\n Enjoy this 20% off coupon!" |