#!/bin/bash
#-------------------------------------------------------------------
#		EXPERT SOLUTIONS SARL
#		convert_tpl_to_ejs.sh
#		Convert tpl Smarty template files to EJS template files
#		To execute with bash : bash convert_tpl_to_ejs.sh
#		-x option to vizualize command line
#-------------------------------------------------------------------

# shortcut for charsets match[] and get()
s="[ \t]" 						# space | tab
w="a-zA-Z_0-9" 					# \w seems not work for sed !!! it needs perl extension for regex
								# A-B define A to B charset 
eDol="\\\$"						# $ is parse by bash so we have to escape it : \$ => \\\$
CSObjProp="][$eDol,$w,\,-\.,>"		# carefull ][ must be used at the start of charset 
matchProp="[$CSObjProp]+"		# [charset] + for once or more * for 0 or more ? for 0 or once
matchPropExt="$matchProp+->?$matchProp?->?$matchProp?->?$matchProp?->?$matchProp"
#getProp="($matchPropExt)"			# (content) assign the content to \1 \2 .. \9 in replacement regex
getProp="($matchProp)"			# (content) assign the content to \1 \2 .. \9 in replacement regex
getPropModifier="([$CSObjProp\|]+)"
CSString="$w -><;\.:,'\""
CSStringLight="$w \,-\.><;:"
CSSTranslate="$CSStringLight%"
CSSTranslateModifer="$CSSTranslate\|"
CSRegex="][\\\s\\\w\\\W\, ;\+\*\/$w,-><;\.:" # /[\s, ;]+/
CSMath="\+\*\-\/"
CSMultiline="$CSString\n"
matchString="[$CSString]*"
CSvarname="-$w"
getVarName="['\"]?([$CSvarname]*)['\"]?" # ['"]? are optionnal in smarty
CScompare="!=<>| "
CScall="\(\)\, "
CSFile="-$w\.\/"
matchFile="[$CSFile]*"
getFile="($matchFile)"
CSsomething="$CSObjProp $CScall $CSString"
matchSomething="[$CSsomething]*"
getSomething="($matchSomething)"

# comments
RX100=("\{\*$s*\n" 		"<%# \/\*\n")
RX101=("\n$s*\*\}" 		"\n\*\/ %>")
RX102=("\{\* " 		"<% \/\* ")
RX103=("$s*\*\}" 		" \*\/ %>")

# foreach
RX0=("\{foreach$s+$getSomething$s+as$s+$eDol$getVarName$s+=>$s+$eDol$getVarName$s*\}" 			"<% Object.entries\(\1\)\.forEach\(entry => \{ const \[$eDol\2,$eDol\3\] = entry; %>")
RX1=("\{foreach$s+$getSomething$s+as$s+$eDol$getVarName$s*\}" 									"<% \1\.forEach\($eDol\2 => \{ %>")
RX2=("\{foreach$s+from=$getSomething$s+item=$getVarName$s+name=([$w]*)\}" 						"<% \1\.forEach\($eDol\2 => \{ %>")
RX3=("\{foreach$s+from=$getSomething$s+item=$getVarName$s+key=([$w]*)$s+name=([$eDol,$w]*)\}" 	"<% Object.entries\(\1\)\.forEach(entry => \{ const \[$eDol\3,$eDol\2\] = entry; %>") 
RX4=("\{foreach$s+from=$getSomething$s+item=$getVarName$s+key=([$w]*)$s*\}"						"<% Object.entries\(\1\)\.forEach(entry => \{ const \[$eDol\3,$eDol\2\] = entry; %>") 
RX5=("\{foreach$s+from=$getSomething$s+key=$getVarName$s+item=([$w]*)$s*\}"						"<% Object.entries\(\1\)\.forEach(entry => \{ const \[$eDol\2,$eDol\3\] = entry; %>") 
RX6=("\{foreach$s+from=$getSomething$s+item=$getVarName$s*\}" 									"<% \1\.forEach\($eDol\2 => \{ %>")
RX7=("\{\/foreach\}" 																		"<%  \}\); %>")

# for
RX8=("\{for$s+($eDol[$CSvarname]*)=$getProp$s+to$s+([$CSObjProp$CSMath ]+)$s+step$s+([$CSObjProp$CSMath ]+)\}"	
																				"<% for\(var \1=\2\;\1 <= \3;\1= \1\+\4) \{ %>")
RX9=("\{for$s+($eDol[$CSvarname]*)=$getProp$s+to$s+([$CSObjProp$CSMath ]+)\}"	"<% for\(var \1=\2\;\1 <= \3;\1\+\+) \{ %>")
RX10=("\{\/for\}"			"<% \} %>")

# if 
RX12=("\{if[ \r\n]*(!?[$CSObjProp $CScall $CScompare $CSString]*)[ \$^]*\}" 		"<% if \(\1\) \{ %>")
RX13=("\{elseif$s*\(?([$w]*)\(?([$CSObjProp$CScall$CScompare$CSString]*)\)?\)?$s*\}" 	"<% \} else if \(\1\(\2\)\) \{ %>")
RX14=("\{else\}" 																	"<% \} else \{ %>")
RX15=("\{\/if\}" 																	"<% \} %>")

RX16=("if$s+\(\(([^()]+)\)\)"	"if \(\1\)")
RX17=("if$s+\(([^()]+)\)\)"	"if \(\1\)")
RX18=("if$s+\(\(([^()]+)\)([^)])"	"if \(\1\)\2")

# array
RX20=("array\($getSomething\)"			"\[\1\]")
RX21=("\(array\)"						"") # delete cast array
# delete duster
RX22=("\|explode:([$CSObjProp]*|['\"][$CSStringLight]*['\"]):[0-9]"	"\|explode:\1")

# include other tpl
RX23=("\{include$s*file=['\"]\.\/?$getFile.[a-zA-Z]{3}['\"]$s*\}" 				"<%- includeEJS('\1',locals) %>")
RX24=("\{include$s*file=$getProp$s*\}" 											"<%- includeEJS(\1,locals) %>")

# print_r
RX25=("\{print_r\($getProp\)$s*\}"	"<%- \1 %>")

# translate
RX30=("\{l$s*s=([$CSObjProp$CSSTranslate\|]*)$s+sprintf=\[([$CSObjProp $CSMath]*)\]$s+mod=$getVarName(\|[$CSString]*)?$s*\}" 
																				"<%= transl\(\1,\'\3\'\4,\(\2\)\) %>")
RX31=("\{l$s*s=(['\"']?[$CSObjProp$CSSTranslate]*['\"']?\|?[$CSString]*)$s+mod=$getVarName(\|[$CSString]*)?$s*\}" 
																				"<%= transl\(\1,\'\2\'\3\) %>")
RX32=("\{l$s+s=([$CSObjProp$CSSTranslate\|]*)$s+mod[e]?=$getPropModifier$s*?\}" "<%= transl\(\1,\2\) %>")
#RX32=("\{l$s+s=([$CSObjProp$CSSTranslate]*)(\|[$CSString]$s+mod[e]?=$getVarName$s*\t*)?\}" "<%= transl\(\1\3,\'\2\'\) %>")
RX33=("\{l$s+s=([$CSObjProp$CSSTranslate\|]*)$s*(\|[$CSString]*)?$s*\}" 				"<%= transl\(\1,\'\'\) %>")
RX34=("\{l$s+s=(['\"]?[$CSSTranslate ]*['\"]?)(\|[$CSString]*)?$s*\}" 					"<%= transl\(\1\2,\'\'\) %>")


# Clariprint register function
RX40=("\{([Cd][$w]+)$s+$getVarName=$getProp$s+$getVarName=$getProp$s*\}"			"<% \1\(§\2 : \3\, \4 : \5£, locals\) %>")
RX41=("\{([Cd][$w]+)$s+$getVarName=$getVarName$s+$getVarName=$getVarName$s*\}"		"<% \1\(§\2 : '\3\',\4 : '\5\'£, locals\) %>")
RX42=("\{([Cd][$w]+)$s+$getVarName=$getProp$s*\}" 									"<% \1\(§\2 : \3£, locals\) %>")
RX43=("\{([Cd][$w]+)$s+$getVarName=$getVarName$s*\}"								"<% \1\(§\2 : '\3\'£, locals\) %>")

# macro assign and display vars, other register function call
RX50=("\{$s*$getProp\|([$w]+)$s*(nofilter)?$s*\}" 									"<%= \2\(\1\) %>")
RX51=("\{$s*$getProp$s*(nofilter)?$s*\}" 											"<%= \1 %>")
RX52=("\{$s*(\(int\)?\(?$eDol[$CSObjProp $CSMath]*\)?)$s*\}" 						"<%= \1 %>")
#RX43=("\{$s*([$CSObjProp$CScall'\"]+)\:(['\"]?[$CSObjProp]+['\"]?)$s*(nofilter)?$s*\}"		"<%= \2_\1 %>")
RX53=("\{$s+([$CSObjProp$CScall'\"]+):(['\"][$w\,-\.]+['\"])$s*\}"		"<%= \2_\1 %>")
RX54=("\{$s+([$CSObjProp$CScall'\"\|:]*)$s*(nofilter)?$s*\}"							"<%= \1 %>")
RX55=("\{assign$s+var=$getVarName$s+value=([$CSObjProp,$CScall,$CSMultiline|]*)$s*\}" 	"<% var $eDol\1 = \2\ %>")
RX56=("\{($eDol[$w]*)=([$CSObjProp,$CScall,$CSString]*)\}" 						"<% \1 = \2; %>")

# final replace of {...}, next regex will not be able to catch {} !!!
RX57=("\{$s*([$CSObjProp$CScall'\"\|:]+)$s*\}"									"<%= \1 %>")

# modifiers |<modifier>:param1:param2 ...
RX60=("=([$CSObjProp,$CSMultiline]*)\|explode:([$CSObjProp]*):?[0-9]?"					"=explode\(\1,\2\)")
RX61=("=([$CSObjProp,$CSMultiline]*)\|explode:(['\"][$CSStringLight]*)['\"]:?[0-9]?"	"=explode\(\1,\2\)")
RX62=("['\"]([$CSRegex]+)['\"]\|preg_split:$getProp" 						"\2.split\('\1'\)")
RX63=("['\"]([$CSRegex]+)['\"]\|([$w]+):$getProp" 							"\2\(\3,'\1')")
RX64=("$getProp\|([$w]+):$getVarName:$getVarName"							"\2\(\1,'\3','\4'\)")
RX65=("$getProp\|([$w]+):$getVarName" 										"\2\(\1,'\3'\)")
RX66=("['\"]([$CSRegex]+)['\"]\|([$w]+):$getProp" 							"\2\('\1',\3)")
RX67=("([$CSvarname]*)\(([$CSObjProp\,$CSString]*)\)\|([$w]*):$getVarName" 	"\3\(\1\(\2\),'\4')")
RX68=("$getProp\|([$w]+)"													"\2\(\1\)")

# main functions
RX70=("explode\($s*([$CSObjProp,$CSMultiline]*)$s*\,$s*$getProp$s*\)" 			"\2\.split\(\1\)")
RX71=("in_array_silent\($s*$getProp$s*\,$s*$getProp$s*\)" 						"\2\.includes\(\1\)")
RX72=("in_array_silent\($s*$getVarName$s*\,$s*$getProp$s*\)"					"\2\.includes\('\1\')")
RX73=("count\($s*$getProp$s*\)" 												"\(function \(\) \{if \(Array.isArray\(\1\)\) return \1; else return Object.keys\(\1\);\}\(\)\).length")
RX74=("end\($s*$getProp$s*\)" 													"\1\.at(-1)")
RX75=("isset\($s*$getProp$s*\)" 												"\1 !== undefined")

# cast and type 
RX80=("\(int\)\(?$s*$getProp($s*[$CSMath]+$s*[0-9]*$s*)\)?"						"parseInt\(\1\,10\)\2")
RX81=("\(int\)(\($s*)?$getProp($s*\))?"										"parseInt\(\2\,10\)")
RX82=("is_object\($s*$getProp$s*\)"	"typeof \1 == 'object'")

# symbols
RX90=("->($eDol[$w]+)" 			"\[\1\]")
RX91=("->([$w]+)" 					"\.\1")
RX92=(" != " 						" !== ")
RX98=("§"	"{")
RX99=("£"	"}")


echo start convert all .tpl files of current dir, result in new ejs/ dir ...

rm -rf ejs
mkdir ejs

cp *.tpl ejs/
cd ejs
rename "s/.tpl/.ejs/" *.tpl

for rxi in {0..110};
#for rxi in {5..5};
do
	snam="RX$rxi[0]"
	if [ "${!snam}" != "" ] ;
 	then 
		rnam="RX$rxi[1]"
		echo \#$rxi search "s/${!snam}/"
		echo \#$rxi replace by "${!rnam}/g"
		ls -1 *.ejs | xargs -i@ sed -r -E -i ":a;N;\$!ba;s/${!snam}/${!rnam}/g" @ 
		# (:a;N;$!ba) read the whole file in a loop, then replaces the newline(s) # without it all regex with \n failded
		# see https://stackoverflow.com/questions/1251999/how-can-i-replace-each-newline-n-with-a-space-using-sed
	fi
done
echo --------------------------------
echo finish
ls -al