├── .gitignore ├── test.scml ├── head.scml ├── Cargo.toml ├── Cargo.lock ├── src ├── main.rs ├── html_processing.rs └── js_processing.rs ├── app.html ├── gen.scml ├── app.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /test.scml: -------------------------------------------------------------------------------- 1 |

hello world

2 | 3 | -------------------------------------------------------------------------------- /head.scml: -------------------------------------------------------------------------------- 1 | [html] 2 |

Header one

3 | in[sell] 4 | [html] 5 | 6 | [html sell] 7 |

sell one

8 | [html] -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "scml" 3 | version = "0.1.0" 4 | authors = ["valentine-mario "] 5 | edition = "2018" 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | regex = "1" 11 | 12 | [target.x86_64-pc-windows-gnu] 13 | linker="x86_64-pc-windows-gnu" 14 | 15 | [target.x86_64-unknown-linux-musl] 16 | linker="x86_64-unknown-linux-musl" 17 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "aho-corasick" 5 | version = "0.7.10" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" 8 | dependencies = [ 9 | "memchr", 10 | ] 11 | 12 | [[package]] 13 | name = "lazy_static" 14 | version = "1.4.0" 15 | source = "registry+https://github.com/rust-lang/crates.io-index" 16 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 17 | 18 | [[package]] 19 | name = "memchr" 20 | version = "2.3.3" 21 | source = "registry+https://github.com/rust-lang/crates.io-index" 22 | checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" 23 | 24 | [[package]] 25 | name = "regex" 26 | version = "1.3.7" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | checksum = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692" 29 | dependencies = [ 30 | "aho-corasick", 31 | "memchr", 32 | "regex-syntax", 33 | "thread_local", 34 | ] 35 | 36 | [[package]] 37 | name = "regex-syntax" 38 | version = "0.6.17" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" 41 | 42 | [[package]] 43 | name = "scml" 44 | version = "0.1.0" 45 | dependencies = [ 46 | "regex", 47 | ] 48 | 49 | [[package]] 50 | name = "thread_local" 51 | version = "1.0.1" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" 54 | dependencies = [ 55 | "lazy_static", 56 | ] 57 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | mod html_processing; 2 | use crate::html_processing::process_html; 3 | use std::env; 4 | use std::process; 5 | use regex::Regex; 6 | mod js_processing; 7 | use crate::js_processing::process_js; 8 | 9 | fn main() { 10 | 11 | let args = env::args(); 12 | 13 | 14 | let get_filename = process_html::Config::new(args).unwrap_or_else(|error| { 15 | eprintln!("{}", error); 16 | process::exit(1); 17 | }); 18 | let file_content=process_html::read_file(&get_filename.filename).unwrap_or_else(|err| { 19 | eprintln!("Problem reading file: {}", err); 20 | process::exit(1) 21 | }); 22 | println!("processing html"); 23 | let comment_re = Regex::new(r"(?m)####.*\n").unwrap(); 24 | let file_content = comment_re.replace_all(&file_content, "\n\n"); 25 | 26 | let file_content_from_another_file=process_html::replace_file(&file_content); 27 | let file_content=file_content_from_another_file.replace("\n", ""); 28 | let hash_value=process_html::generate_scml_hash(&file_content); 29 | 30 | let final_string=process_html::replace_variable(&file_content, &hash_value); 31 | 32 | let mut generaic_seg=process_html::replace_variable_parameter(&final_string, &hash_value); 33 | 34 | for _i in 0..10{ 35 | generaic_seg=process_html::replace_variable_parameter(&generaic_seg, &hash_value); 36 | } 37 | let vector=process_js::process_innerjs(&generaic_seg); 38 | if vector.len()>0 { 39 | println!("processing javascript"); 40 | } 41 | 42 | 43 | process_html::write_to_js_file(&vector, &get_filename).unwrap_or_else(|error|{ 44 | eprintln!("problem writing to file {}", error); 45 | process::exit(1); 46 | }); 47 | 48 | 49 | let re= Regex::new(r#"\[html (\w+)\].*?\{\{.+?\}\}.*?\[html\]|\[\s*?html \w*?\s*?\]|append\s*?=\s*?(.+?)\s*?end|limit\s*?=\s*?(\d{1,})|innerHTML\s*?=\s*?(\w+)|getValue\s*?=\s*?(\w+)|disable\s*?=\s*?true|(\w+)\s*?=\s*?\{(.*?)\}\s*?|formatInt|formatFloat|visibility\s*?=\s*?(\w+)|formatDate\s*?=\s*?(\w+/\w+/\w+)\s*?|formatTimeAgo|formatCurrency\s*?=\s*?["|']\s*?(\w+)\s*?["|']|reverseString|shortenNum|onChange=\s*?(\w+)|submitForm\s*?\[(.+?)\]\s*?=\s*?(\w+)|shareDefault=\s*?["|']\s*?(\w+)\s*?["|']|shareCustome\s*?\[\s*?(.*?)\s*?\]\s*?=\s*?["|']\s*?(\w+)\s*?["|']|copyArea=\s*?(\w+)"#).unwrap(); 50 | let result=re.replace_all(&generaic_seg, "").to_string(); 51 | 52 | 53 | process_html::write_to_html_file(&result, &get_filename).unwrap_or_else(|error|{ 54 | eprintln!("problem writing to file {}", error); 55 | process::exit(1); 56 | }); 57 | } 58 | 59 | -------------------------------------------------------------------------------- /app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | app 7 | 8 | 9 | 10 | 11 |

Age: 34

title:chief

hi: kenneth

age: 44

sex: male

i said hello 12 |

hi: Val

age: 23

sex: male

i said hello

Age: 54

title:Collect

hi: Valium

age: 23

sex: male

i said hello

hi: Ibe

age: 23

sex: male

i said hello

hi: Craige

age: 23

sex: male

i said hello

hi: Valent

age: 23

sex: male

i said hello 13 |

Header one

sell one

14 |

sell one

15 |

hello world

this is some long ass text longer than 10 char

--------

16 |

section two start

This is some text

17 |
foodie here

10000

10000.234

18 | #this is a comment

text four

2020-06-10T17:47:29.156Z
2020-06-10T17:47:29.156Z
2020-06-10T17:47:29.156Z
2020-06-10T17:47:29.156Z
2020-06-16T17:47:29.156Z
19 |

1000

1000

this is some text fuckers

12000

12000000

1000

1000

this is some text fuckers

12000

12000000

10000

10000.234

hello world

this is some long ass text longer than 10 char

--------

21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /gen.scml: -------------------------------------------------------------------------------- 1 | [html onesense] 2 |

hi: {{name}}

3 |

age: {{age}}

4 |

sex: {{sex}}

5 | i said hello 6 | [html] 7 | 8 | [html twosense] 9 |

Age: {{age}}

10 |

title:{{title}}

11 | [html] 12 | 13 | [html] 14 | in[twosense:[age="34" title="chief"]] 15 | in[onesense:[name="kenneth" age="44" sex="male"]] 16 | [html] 17 | in[onesense:[name="Val" age="23" sex="male"]] 18 | in[twosense:[age="54" title="Collect"]] 19 | 20 | in[onesense:[name="Valium" age="23" sex="male"]] 21 | 22 | in[onesense:[name="Ibe" age="23" sex="male"]] 23 | 24 | in[onesense:[name="Craige" age="23" sex="male"]] 25 | 26 | in[onesense:[name="Valent" age="23" sex="male"]] 27 | 28 | 29 | inFile[head.scml] 30 | [html one] 31 |

hello world

32 | this is some long ass text longer than 10 char 33 | 34 |

--------

35 | [html] 36 | 37 | [html two] 38 |

section two start

39 |

This is some text

40 |
41 | 42 | 43 |
44 | [html] 45 | 46 | [html three] 47 | 48 |
foodie here
49 | 50 | 51 |

10000

52 |

10000.234

53 | [html] 54 | 55 | [html four] 56 | #this is a comment 57 |

text four

58 |

2020-06-10T17:47:29.156Z
59 |
2020-06-10T17:47:29.156Z
60 |
2020-06-10T17:47:29.156Z
61 |
2020-06-10T17:47:29.156Z
62 |
2020-06-16T17:47:29.156Z
63 | [html] 64 | 65 | [html five] 66 |

1000

67 |

1000

68 |

this is some text fuckers

69 |

12000

70 |

12000000

71 |

72 | 73 |
74 | 75 | 76 | 77 |
78 |
79 | 80 | 81 |
82 | 94 | in[five:[name="val house" age="34" date="23/34/2020"]] 95 | in[three:[name="kin" age="44" date="23/34/2020"]] 96 | 97 | 98 | in[one] 99 | [html] 100 | 101 | -------------------------------------------------------------------------------- /src/html_processing.rs: -------------------------------------------------------------------------------- 1 | pub mod process_html{ 2 | use std::collections::HashMap; 3 | use regex::Regex; 4 | use std::path::Path; 5 | use std::fs; 6 | use std::error::Error; 7 | use std::fs::File; 8 | use std::io::prelude::*; 9 | use std::process; 10 | use std::ffi::OsStr; 11 | 12 | 13 | pub fn replace_variable(scml_string:&str, scml_hash:&HashMap)->String{ 14 | let mut tmp=String::from(scml_string); 15 | 16 | //loop through 20 times to be sure all values of in are correctly replaced 17 | for _i in 1..50{ 18 | for (key, value) in scml_hash{ 19 | let key=format!("in[{}]", key); 20 | tmp=tmp.replace(&key, value); 21 | 22 | } 23 | 24 | } 25 | 26 | tmp 27 | } 28 | 29 | pub fn replace_file(scml_string:&str)->String{ 30 | let mut tmp=String::from(scml_string); 31 | let file_match=Regex::new(r#"inFile\[(.+?\.scml)\]"#).unwrap(); 32 | for val in file_match.captures_iter(scml_string){ 33 | let file_content= read_file(&String::from(val.get(1).unwrap().as_str())).unwrap_or_else(|err| { 34 | eprintln!("Problem reading file: {}", err); 35 | process::exit(1) 36 | }); 37 | let process_file=replace_file(&file_content); 38 | let string_format=format!("inFile[{}]", val.get(1).unwrap().as_str()); 39 | tmp=tmp.replace(&string_format, &process_file) 40 | } 41 | tmp 42 | } 43 | 44 | pub fn replace_variable_parameter(scml_string:&str, scml_hash:&HashMap)->String{ 45 | let mut tmp=String::from(scml_string); 46 | 47 | for (key, value) in scml_hash{ 48 | //get hash conten 49 | let mut key_content= value.to_string(); 50 | 51 | //in[seg_name:[name="value"]] 52 | let string_target=format!(r#"in\[{}\s*?:\s*?(\[\w+=\s*?["|']\s*?.+?\s*?["|']\s*?\]+?)\s*?\]"#, key); 53 | let string_regex=Regex::new(&string_target).unwrap(); 54 | 55 | let variables=format!(r#"(\w+)=\s*?["|']\s*?(.+?)\s*?["|']\s*?"#); 56 | let string_variables=Regex::new(&variables).unwrap(); 57 | for val in string_regex.captures_iter(scml_string){ 58 | for val2 in string_variables.captures_iter(val.get(1).unwrap().as_str()){ 59 | 60 | let key=format!(r#"{{{{{}}}}}"#, val2.get(1).unwrap().as_str()); 61 | 62 | key_content=key_content.replace(&key, val2.get(2).unwrap().as_str()); 63 | } 64 | 65 | } 66 | 67 | tmp=string_regex.replace(&tmp, key_content.as_str()).to_string(); 68 | } 69 | 70 | tmp 71 | } 72 | 73 | 74 | pub fn generate_scml_hash(value:&str)->HashMap{ 75 | let re= Regex::new(r"\[html (\w+)\]\s*?(.+?)\s*?\[html\]").unwrap(); 76 | let mut html_id = HashMap::new(); 77 | 78 | if re.is_match(value){ 79 | for val in re.captures_iter(value){ 80 | html_id.insert(String::from(val.get(1).unwrap().as_str()), String::from(val.get(2).unwrap().as_str())); 81 | } 82 | } 83 | 84 | html_id 85 | } 86 | #[derive(Debug)] 87 | pub struct Config { 88 | pub filename: String, 89 | pub new_file:String 90 | } 91 | impl Config { 92 | pub fn new(mut value: std::env::Args) -> Result { 93 | if value.len() < 3 { 94 | println!(" 95 | Inavlid number of arguments parsed 96 | SCML CLI options 97 | Options:\n\tscml scml_path new_file_name => Transpile SCML and create HTML and JS 98 | 99 | Author: Oragbakosi Valentine 100 | "); 101 | return Err(""); 102 | }else { 103 | value.next(); 104 | let filename = match value.next() { 105 | Some(arg) => arg, 106 | None => return Err("Didn't get a file name"), 107 | }; 108 | let new_file = match value.next() { 109 | Some(arg) => arg, 110 | None => return Err("Didn't get a file name"), 111 | }; 112 | 113 | Ok(Config { 114 | filename, 115 | new_file 116 | }) 117 | } 118 | } 119 | } 120 | pub fn read_file(path:&String)->Result>{ 121 | if Path::new(&path).extension().and_then(OsStr::to_str)== Some("scml"){ 122 | let content = fs::read_to_string(Path::new(&path))?; 123 | return Ok(content); 124 | }else{ 125 | panic!("cannot read none scml file") 126 | } 127 | } 128 | 129 | pub fn write_to_html_file(value:&str, config:&Config)-> Result<(), Box>{ 130 | let output_filename = &config.new_file; 131 | let mut output_filename = String::from(output_filename); 132 | output_filename.push_str(".html"); 133 | let mut outfile = File::create(output_filename.to_string())?; 134 | let token= value.split("[html]"); 135 | let trailing_html=format!("\n \n 136 | \n 137 | {}\n 138 | \n 139 | ", &config.new_file); 140 | outfile.write_all(&trailing_html.as_bytes())?; 141 | for line in token { 142 | outfile.write_all(line.as_bytes())?; 143 | outfile.write_all(b"\n")? 144 | } 145 | let ending_html=format!(" 146 | 147 | ", &config.new_file); 148 | outfile.write_all(&ending_html.as_bytes())?; 149 | Ok(()) 150 | } 151 | 152 | pub fn write_to_js_file(value:&Vec, config:&Config)->Result<(), Box>{ 153 | let output_filename = &config.new_file; 154 | let mut output_filename = String::from(output_filename); 155 | output_filename.push_str(".js"); 156 | let mut outfile = File::create(output_filename.to_string())?; 157 | 158 | for i in value { 159 | outfile.write_all(i.as_bytes())?; 160 | outfile.write_all(b"\n\n")? 161 | } 162 | Ok(()) 163 | } 164 | 165 | } 166 | #[cfg(test)] 167 | mod test{ 168 | use super::*; 169 | use std::collections::HashMap; 170 | 171 | 172 | #[test] 173 | fn test_replace_variable(){ 174 | let mut test_hash:HashMap = HashMap::new(); 175 | test_hash.insert(String::from("segment"), String::from("

hello world

")); 176 | let test_string=format!("in[segment]"); 177 | let new_value= process_html::replace_variable(&test_string, &test_hash); 178 | assert_eq!(new_value, "

hello world

"); 179 | } 180 | 181 | #[test] 182 | fn test_replace_file(){ 183 | let file_path=String::from("inFile[test.scml]"); 184 | let new_value=process_html::replace_file(&file_path); 185 | assert_eq!(new_value, "

hello world

") 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | let var1= document.getElementById("food").innerHTML; 2 | 3 | 4 | let var1= document.getElementById("food").innerHTML; 5 | 6 | 7 | let var2=document.getElementById("getter").value; 8 | 9 | 10 | let var2=document.getElementById("getter").value; 11 | 12 | 13 | document.getElementById("start").innerHTML="a whole new world"; 14 | 15 | 16 | document.getElementById("start").innerHTML="a whole new world"; 17 | 18 | 19 | document.getElementById("some").innerHTML= document.getElementById("some").innerHTML.substring(0, 10); 20 | 21 | 22 | document.getElementById("some").innerHTML= document.getElementById("some").innerHTML.substring(0, 10); 23 | 24 | 25 | document.getElementById("user").disabled=true; 26 | 27 | 28 | document.getElementById("text").disabled=true; 29 | 30 | 31 | document.getElementById("text").disabled=true; 32 | 33 | 34 | document.getElementById("user").disabled=true; 35 | 36 | 37 | document.getElementById("but").addEventListener("click", ()=>{ 38 | console.log("hi");console.log("zee") }); 39 | 40 | 41 | document.getElementById("but").addEventListener("click", ()=>{ 42 | console.log("hi");console.log("zee") }); 43 | 44 | 45 | document.getElementById("num1").innerHTML= Intl.NumberFormat().format(parseInt(document.getElementById("num1").innerHTML)); 46 | 47 | 48 | document.getElementById("num1").innerHTML= Intl.NumberFormat().format(parseInt(document.getElementById("num1").innerHTML)); 49 | 50 | 51 | document.getElementById("num2").innerHTML= Intl.NumberFormat().format(parseFloat(document.getElementById("num2").innerHTML)); 52 | 53 | 54 | document.getElementById("num2").innerHTML= Intl.NumberFormat().format(parseFloat(document.getElementById("num2").innerHTML)); 55 | 56 | 57 | document.getElementById("money").innerHTML='$'+ Intl.NumberFormat().format(parseFloat(document.getElementById("money").innerHTML)); 58 | 59 | 60 | document.getElementById("money2").innerHTML='€'+ Intl.NumberFormat().format(parseFloat(document.getElementById("money2").innerHTML)); 61 | 62 | 63 | document.getElementById("money").innerHTML='$'+ Intl.NumberFormat().format(parseFloat(document.getElementById("money").innerHTML)); 64 | 65 | 66 | document.getElementById("money2").innerHTML='€'+ Intl.NumberFormat().format(parseFloat(document.getElementById("money2").innerHTML)); 67 | 68 | 69 | document.getElementById("four_head").style.visibility = "visible"; 70 | 71 | 72 | function timeAgo(date) { 73 | 74 | var seconds = Math.floor((new Date() - date) / 1000); 75 | 76 | var interval = Math.floor(seconds / 31536000); 77 | 78 | if (interval > 1) { 79 | return interval + ' years ago'; 80 | } 81 | interval = Math.floor(seconds / 2592000); 82 | if (interval > 1) { 83 | return interval + ' months ago'; 84 | } 85 | interval = Math.floor(seconds / 86400); 86 | if (interval > 1) { 87 | return interval + ' days ago'; 88 | } 89 | interval = Math.floor(seconds / 3600); 90 | if (interval > 1) { 91 | return interval + ' hours ago'; 92 | } 93 | interval = Math.floor(seconds / 60); 94 | if (interval > 1) { 95 | return interval + ' minutes ago'; 96 | } 97 | return Math.floor(seconds) + ' seconds ago'; 98 | } 99 | 100 | 101 | document.getElementById('some_date2').innerHTML=timeAgo(new Date(document.getElementById('some_date2').innerHTML).getTime()) 102 | 103 | 104 | document.getElementById('some_date5').innerHTML=timeAgo(new Date(document.getElementById('some_date5').innerHTML).getTime()) 105 | 106 | 107 | document.getElementById("some_date").innerHTML= new Date(Date.parse(document.getElementById("some_date").innerHTML)).getDate()+'/'+parseInt(new Date(Date.parse(document.getElementById("some_date").innerHTML)).getMonth()+1) +'/'+new Date(Date.parse(document.getElementById("some_date").innerHTML)).getFullYear() 108 | 109 | 110 | document.getElementById("some_date3").innerHTML= parseInt(new Date(Date.parse(document.getElementById("some_date3").innerHTML)).getMonth()+1)+'/' + new Date(Date.parse(document.getElementById("some_date3").innerHTML)).getDate()+'/'+new Date(Date.parse(document.getElementById("some_date3").innerHTML)).getFullYear() 111 | 112 | 113 | document.getElementById("some_date4").innerHTML= new Date(Date.parse(document.getElementById("some_date4").innerHTML)).getFullYear()+ '/'+ parseInt(new Date(Date.parse(document.getElementById("some_date4").innerHTML)).getMonth()+1) +'/'+ new Date(Date.parse(document.getElementById("some_date4").innerHTML)).getDate() 114 | 115 | 116 | document.getElementById('my_sring').innerHTML= document.getElementById('my_sring').innerHTML.split(' ').reverse().join(' ') 117 | 118 | 119 | document.getElementById('my_sring').innerHTML= document.getElementById('my_sring').innerHTML.split(' ').reverse().join(' ') 120 | 121 | 122 | function NumFormatter(num) { 123 | if(Math.abs(num) < 999){ 124 | return Math.sign(num)*Math.abs(num) 125 | }else if(Math.abs(num) > 999 && Math.abs(num) < 1000000){ 126 | return Math.sign(num)*((Math.abs(num)/1000).toFixed(2)) + 'k' 127 | }else if(Math.abs(num) > 999999 && Math.abs(num) < 1000000000) 128 | { 129 | return Math.sign(num)*((Math.abs(num)/1000000).toFixed(2)) + 'M' 130 | }else if(Math.abs(num) > 999999999 && Math.abs(num) < 1000000000000){ 131 | return Math.sign(num)*((Math.abs(num)/1000000000).toFixed(2)) + 'B' 132 | }else if(Math.abs(num) > 999999999999 && Math.abs(num) < 1000000000000000){ 133 | return Math.sign(num)*((Math.abs(num)/1000000000000).toFixed(2)) + 'T' 134 | } 135 | } 136 | 137 | 138 | document.getElementById('ccc').innerHTML=NumFormatter(parseInt(document.getElementById('ccc').innerHTML)) 139 | 140 | 141 | document.getElementById('cccd').innerHTML=NumFormatter(parseInt(document.getElementById('cccd').innerHTML)) 142 | 143 | 144 | document.getElementById('ccc').innerHTML=NumFormatter(parseInt(document.getElementById('ccc').innerHTML)) 145 | 146 | 147 | document.getElementById('cccd').innerHTML=NumFormatter(parseInt(document.getElementById('cccd').innerHTML)) 148 | 149 | 150 | document.getElementById('writter').addEventListener('input', (event)=>{ 151 | document.getElementById('write').innerHTML=event.target.value 152 | }) 153 | 154 | 155 | document.getElementById('writter').addEventListener('input', (event)=>{ 156 | document.getElementById('write').innerHTML=event.target.value 157 | }) 158 | 159 | 160 | function getForm(form){ 161 | var elements = document.getElementById(form).elements; 162 | var obj ={}; 163 | for(var i = 0 ; i < elements.length ; i++){ 164 | var item = elements.item(i); 165 | obj[item.name] = item.value; 166 | if(obj[item.name]==''){ 167 | delete obj[item.name]; 168 | } 169 | } 170 | return obj 171 | } 172 | 173 | 174 | document.getElementById('mybut').addEventListener('click', (event)=>{ 175 | event.preventDefault(); 176 | fetch('https://rocky-mesa-69765.herokuapp.com/email/add', { 177 | method: 'POST', 178 | headers: { 179 | 'Content-Type': 'application/json' 180 | }, 181 | body:JSON.stringify(getForm('myForm')) 182 | }).then((res) => res.json()) 183 | .then((data) => console.log(data)) 184 | .catch((err)=>console.log(err)) 185 | }) 186 | 187 | 188 | var pageUrl=window.location.href; 189 | 190 | var link1 = document.getElementById('link1'); 191 | link1.href='https://www.facebook.com/sharer.php?u='+pageUrl; 192 | document.body.appendChild(link1) 193 | ; 194 | 195 | 196 | var link2 = document.getElementById('link2'); 197 | link2.href='https://twitter.com/intent/tweet?url='+pageUrl; 198 | document.body.appendChild(link2) 199 | ; 200 | 201 | 202 | var link1 = document.getElementById('link1'); 203 | link1.href='https://www.facebook.com/sharer.php?u='+pageUrl; 204 | document.body.appendChild(link1) 205 | ; 206 | 207 | 208 | var link2 = document.getElementById('link2'); 209 | link2.href='https://twitter.com/intent/tweet?url='+pageUrl; 210 | document.body.appendChild(link2) 211 | ; 212 | 213 | 214 | var link3 = document.getElementById('link3'); 215 | link3.href='https://t.me/share/url?url='+'www.google.com'; 216 | document.body.appendChild(link3) 217 | ; 218 | 219 | 220 | var link4 = document.getElementById('link4'); 221 | link4.href='https://api.whatsapp.com/send?text='+'www.google.com'; 222 | document.body.appendChild(link4) 223 | ; 224 | 225 | 226 | var link3 = document.getElementById('link3'); 227 | link3.href='https://t.me/share/url?url='+'www.google.com'; 228 | document.body.appendChild(link3) 229 | ; 230 | 231 | 232 | var link4 = document.getElementById('link4'); 233 | link4.href='https://api.whatsapp.com/send?text='+'www.google.com'; 234 | document.body.appendChild(link4) 235 | ; 236 | 237 | 238 | function copyToClip(id){ 239 | var copyText = document.getElementById(id); 240 | var textArea = document.createElement('textarea'); 241 | textArea.value = copyText.textContent; 242 | document.body.appendChild(textArea); 243 | textArea.select(); 244 | document.execCommand('Copy'); 245 | textArea.remove(); 246 | } 247 | 248 | 249 | document.getElementById('copy_me').addEventListener('click', (e)=>{ 250 | e.preventDefault(); 251 | copyToClip('to_copy') 252 | }) 253 | 254 | 255 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SCML (Scripting Markup Language) 2 | 3 | Scripting Markup Language is a custom easy to use markup language with HTML-like syntax with extra features that transpile to Javascript and HTML. 4 | 5 | 6 | The idea of SCML was to give simple markup extra features, that anyone can easily get started with and get a web page running with little knowledge of JS. It allows you to write less and get more! It is written entirely in the Rust programming language. 7 | 8 | To download the binary for the cli [click](https://github.com/Valentine-Mario/SCML/releases/tag/1.1.0) 9 | 10 | - For Linux users: Place the binary in your **/usr/bin** or **/usr/local/bin** directory to make the CLI command globally accessible 11 | - You might need to run the chmod command first **chmod +x scml** 12 | 13 | - For Windows users: 14 | 15 | Open start menu, 16 | 17 | Type **Edit environment variables** 18 | Open the option **Edit the system environment variables** 19 | Click **Environment variables**... button 20 | There you see two boxes, in **System Variables** box find **path** variable 21 | Click **Edit** 22 | a window pops up, click **New** 23 | Type the Directory path of your **.exe** file 24 | Click **Ok** on all open windows and restart the command prompt. 25 | 26 | - To use the CLI: Assuming I have created an SCML file called **file.scml** and I wish it to be transpiled to a new JS and HTML file called **home.js and home.html**, open your terminal and run the command 27 | 28 | ``` 29 | scml file.scml home 30 | 31 | ``` 32 | Easy!!! :smiley: 33 | 34 | ## HTML PROCESSING 35 | 36 | SCML gives features that allow you reuse HTML segments, import SCML files, and reuse segments from other SCML files. 37 | 38 | #### Reuse HTML segments 39 | 40 | SCML html segments are enclosed in square braces as such: 41 | 42 | ``` 43 | [html] 44 |

hello world

45 | [html] 46 | 47 | ``` 48 | This is a simple anonymous HTML segment that can't be reused. To create a named segment that can be reused, the syntax is as thus: 49 | 50 | ``` 51 | [html segment_1] 52 |

hello segment 1

53 |

are you ready to go

54 | [html] 55 | 56 | ``` 57 | where `segment_1` is the name. 58 | Note: Segment naming follows the same protocol as variable naming. 59 | 60 | To reuse a segment, simply use the syntax in[segment_name]. Let's take the example above: 61 | Presuming I have an anonymous segment and I wish to reuse segment_1 in it 62 | 63 | ``` 64 | [html] 65 |

hello world

66 | in[segment_1] 67 | [html] 68 | 69 | ``` 70 | Since the content of segment_1 is: 71 | 72 | ``` 73 |

hello segmnent 1

74 |

are you ready to go

75 | 76 | ``` 77 | The transpiled HTML content would be 78 | 79 | ``` 80 |

hello world

81 |

hello segment 1

82 |

are you ready to go

83 | 84 | ``` 85 | Go ahead and try it on your own. :relaxed: Be careful not to leave extra spaces when importing a segment eg in[ segment_1], in [segment_1], would be ignored by the scml transpiler. 86 | 87 | With SCML, you can also nest import. Take the following example: 88 | 89 | ``` 90 | [html seg_1] 91 |
Hi
92 | [html] 93 | 94 | [html seg_2] 95 |

hi dear

96 | in[seg_1] 97 | [html] 98 | 99 | [html] 100 |
final
101 | in[seg_2] 102 | [html] 103 | 104 | ``` 105 | 106 | 107 | Notice that seg_2 imports seg_1 but the final segment does not directly call seg_1. But because the anonymous segment calls seg_2 which calls seg_1, it would import seg_1 along with it. And this can go on 20 layers deep :scream: 108 | 109 | Note: Avoid importing segments in itself. 110 | 111 | #### Import SCML files and reuse segments from other files 112 | 113 | 114 | SCML also allows you reuse other SCML files. Instead of rewriting headers and footers for every HTML files, you can easily create an SCML header and footer file, then import it to be used in your current file using the syntax inFile[path_to_scml]. Sweet right? :grin: 115 | 116 | 117 | Let's look at an example. 118 | Create a file called **header.scml** and add the following content to it 119 | 120 | ``` 121 | [html] 122 |

Header section

123 | [html] 124 | 125 | ``` 126 | Now create a footer file called **footer.scml** and add the following content 127 | 128 | ``` 129 | [html] 130 |

Footer

131 | [html] 132 | 133 | ``` 134 | 135 | Now finally create create a file called **file.scml** and add the following content 136 | 137 | ``` 138 | inFile[header.scml] 139 | 140 |

This is the body

141 | 142 | inFile[footer.scml] 143 | ``` 144 | 145 | This would replace the inFile with the content of the file when you run the command 146 | 147 | ``` 148 | scml file.scml app 149 | ``` 150 | 151 | Assuming the files you import have segments eg header.scml has a segment called *one* as thus: 152 | 153 | ``` 154 | [html] 155 |

header

156 | [html] 157 | 158 | [html one] 159 |

one here

160 | [html] 161 | ``` 162 | 163 | When this file is imported to another scml file, the segments can also be reused eg: 164 | 165 | ``` 166 | inFile[hedaer.scml] 167 | 168 |

body here

169 | 170 | in[one] 171 | ``` 172 | 173 | Note that this segment *one* isn't in the current scml file but in the header.scml file. But since the file has been imported, the segments are available in the current file. 174 | 175 | Another great feature is that you can also nest importing files eg: 176 | 177 | **file1.scml** 178 | ``` 179 |

this is file one

180 | ``` 181 | 182 | **file2.scml** 183 | ``` 184 |

this is file 2

185 | inFile[file1.scml] 186 | ``` 187 | 188 | **file3.scml** 189 | ``` 190 |

this is file 3

191 | inFile[file2.scml] 192 | ``` 193 | 194 | Notice that file 1 is imported in file 2 while file 2 is imported in file 3. When File 3 is transpiled, it would contain the contents of file 1 and file 2 because it is dependent on file 2 which is dependent on file 1. And of course you can reuse segments in either file 2 or file 1 from file 3. 195 | 196 | 197 | #### Comments 198 | 199 | Adding comments is pretty simple. To add a comment to your SCML code, just start the line with "####" to comment out a particular line 200 | 201 | ``` 202 | [html ind1] 203 | ####this is a comment 204 | [html] 205 | ``` 206 | Commented sections would not be included in the transpiled HTML 207 | 208 | 209 | Note: Avoid using extra spaces when importing files eg: inFile[ file.scml], inFile [file.scml] would be ignored. 210 | 211 | #### Generic segments 212 | 213 | SCML also supports generic segments. This allows you to create a segment template and call it with the parameter values eg: 214 | 215 | ``` 216 | [html seg_1] 217 |

My name is {{name}}

218 |

I am {{age}} years old

219 | [html] 220 | 221 | in[seg_1:[name="valentine" age="50"]] 222 | ``` 223 | 224 | This would replace where you called the segment with the following value 225 | 226 | ``` 227 |

My name is valentine

228 |

I am 50 years old

229 | 230 | ``` 231 | Note that after compiling, the generic segment template is deleted 232 | 233 | ## JS PROCESSING 234 | 235 | SCML also has some helper functions that transpile to your regular javascript. But don't be afraid, this syntax helpers also feel like regular HTML :grin: 236 | 237 | 238 | **Please note that when using JS helper functions the following syntax structure is to be followed 239 | `` 240 | Every tag that uses JS helper function must have an ID and the helper function should come right after the ID. eg 241 | `

` 242 | If you wish to assign class or extra attribues to the tag, it should be added after the helper func eg 243 | `

` 244 | and be sure to use the protocol for naming variables when naming ID because in some cases, some ID would be used as variable names. Improperly formatted syntax would be ignored. Also note that not more than one helper js function should be used per tag else, only the first helper function would be used and the rest ignored. 245 | And finally, avoid reusing segments that contain helper functions since reusing replicates the ID again and ID has to be unique to a tag in HTML** 246 | 247 | 248 | 249 | #### Limit text 250 | To limit text in a tag, use the following syntax: 251 | 252 | ``` 253 |

This text would be limited to the first 10 char

254 | ``` 255 | This would limit the text in the tag to the first 10 char 256 | 257 | #### Get tag content 258 | This allows you to get the content of a tag: 259 | 260 | ``` 261 | get this content 262 | ``` 263 | This would get the content of the tag and assign them to the variable name var1 we decleard above. 264 | 265 | 266 | #### Append text 267 | To append text to a particular html tag, use the following syntax: 268 | 269 | ``` 270 | #to dynamically add static string 271 |

272 | 273 | #to grab text from a string and add it dynamically to another tag using the append helper function 274 |

get this text

275 |

276 | 277 | ``` 278 | This helps you dynamically append the text "Let's go there!!!" to the tag using JS. The end helps specify the end of the sentence or variable. Notice in the second example how i dynamically extracted text from the first tag using innerHTML and used the append to append it into another tag 279 | 280 | #### Get form input 281 | To get the imput from a form: 282 | 283 | ``` 284 | 285 | ``` 286 | This would get the value of the form input and asign them to the variable name var2 287 | 288 | #### Disable 289 | To disable form input or button 290 | 291 | ``` 292 | 293 | ``` 294 | This would disable this form input. It could also be used for button, textarea, etc. 295 | 296 | #### JS expression 297 | You can also write you JS expresion that would be run with an event listener inside your SCML script 298 | 299 | ``` 300 | 306 | ``` 307 | This would run the js expression with the cick event listener. Other supported event listerners include: click, abort, change, animationstart, canplay, copy, dbclick, drag, drop, fullscreenchange, hashchange, input, keydown, keypress, keyup, message, mousedown, mousemove, offline, online, pagehide, paste, pause, play, playing, scroll, search, seeking, seeked, select, volumechange 308 | 309 | #### Format Number 310 | To format a interger number or a float number: 311 | 312 | ``` 313 |

100000

314 | ``` 315 | 316 | ``` 317 |

100000.978

318 | ``` 319 | 320 | #### Visibility 321 | Modify visibility of a tag: 322 | 323 | ``` 324 |

Hide this text

325 | ``` 326 | Other options other than hidden include: collapse, visible, initial, inherit 327 | 328 | #### Format Date 329 | To format a date in-between a tag to dd/mm/yyyy format 330 | 331 | ``` 332 |

2020-06-10T17:47:29.156Z

333 | 334 | ``` 335 | Other date format that could be used include: mm/dd/yyyy and yyyy/mm/dd 336 | 337 | #### Time Ago 338 | To format date to reflect time ago eg 3 days ago, 10 years ago, etc 339 | 340 | ``` 341 |

2020-06-10T17:47:29.156Z

342 | ``` 343 | 344 | #### Format currency 345 | To format currency to dollars: 346 | 347 | ``` 348 |

12000

349 | ``` 350 | Other currency options include: dollar, pounds, naira, yen, euro, and franc 351 | 352 | #### Reverse string 353 | To reverse the string in a html tag: 354 | 355 | ``` 356 |

reverse this string

357 | ``` 358 | 359 | #### Shorten number 360 | To shorten numbers from 1000 to 1K or 1000000 to 1M: 361 | 362 | ``` 363 |

10000

364 | ``` 365 | #### Write from form to tag 366 | To dynbamically update a tag with a form input: 367 | ``` 368 |

369 | 370 | 371 | ``` 372 | As the content of the form input changes, the tag with id write_here is dynamically updated 373 | 374 | #### Submit form input to an endpoint 375 | To submit a form input to an endpoint: 376 | 377 | ``` 378 |
379 | 380 | 381 |
382 | ``` 383 | 384 | notice in the button tag, we did *id="mybut" submitForm[https://submit.com]=myForm*. We pass an id to the button, followed by submitForm[https://submit.com] which contains the submit url, followed by the id of the form we want to submit. 385 | 386 | #### Share link 387 | To create a share link to social media (this is only used with the a tag): 388 | This is to share the default page url 389 | 390 | ``` 391 | facebook 392 | ``` 393 | 394 | While to share with a custom page url 395 | 396 | ``` 397 | facebook 398 | ``` 399 | 400 | Other social media that can be used apart from facebook include: twitter, linkedin, whatsapp, telegram and reddit 401 | 402 | #### Click to copy 403 | To create a click to copy button: 404 | ``` 405 |

i want to copy this

406 | 407 | ``` 408 | Pass in the id of the area you wish to copy to the button. And it would convert it to a click to copy button. 409 | 410 | #### Author 411 | Oragbakosi Valentine 412 | -------------------------------------------------------------------------------- /src/js_processing.rs: -------------------------------------------------------------------------------- 1 | pub mod process_js{ 2 | use regex::Regex; 3 | pub fn process_innerjs(value:&str)->Vec{ 4 | // append text or tag id="id here" append=var_name end> 5 | let append_text=Regex::new(r#"<\s*?\w+?\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?append\s*?=\s*?(.+?)\s*?end\s*?.*?>"#).unwrap(); 6 | 7 | //limit text size in tag 8 | let limit_size= Regex::new(r#"<\s*?\w+?\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?limit\s*?=\s*?(\d{1,}).*?>"#).unwrap(); 9 | 10 | //get inner html text in variable 11 | let inner_html= Regex::new(r#"<\s*?\w+?\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?innerHTML\s*?=\s*?(\w+).*?>"#).unwrap(); 12 | 13 | //get value from a form 14 | let form_value=Regex::new(r#"<\s*?\w+?\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?getValue\s*?=\s*?(\w+).*?>"#).unwrap(); 15 | 16 | //disable or enable input form 17 | let form_disable=Regex::new(r#"<\s*?\w+?\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?disable\s*?=\s*?true.*?>"#).unwrap(); 18 | 19 | //click event 20 | let events=Regex::new(r#"<\s*?\w+?\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?(\w+)\s*?=\s*?\{(.*?)\}.*?>"#).unwrap(); 21 | 22 | //format interger 23 | let format_int=Regex::new(r#"<\s*?\w+?\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?formatInt.*?>"#).unwrap(); 24 | 25 | //format float 26 | let format_float=Regex::new(r#"<\s*?\w+?\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?formatFloat.*?>"#).unwrap(); 27 | 28 | //visibility 29 | let visibility=Regex::new(r#"<\s*?\w+?\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?visibility\s*?=\s*?(\w+).*?>"#).unwrap(); 30 | 31 | //format date 32 | let date_format=Regex::new(r#"<\s*?\w+?\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?formatDate\s*?=\s*?(\w+/\w+/\w+).*?>"#).unwrap(); 33 | 34 | //format date to time ago 35 | let time_age_format=Regex::new(r#"<\s*?\w+?\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?formatTimeAgo.*?>"#).unwrap(); 36 | 37 | //format currency 38 | let format_currency=Regex::new(r#"<\s*?\w+?\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?formatCurrency\s*?=\s*?["|']\s*?(\w+)\s*?["|'].*?>"#).unwrap(); 39 | //reverse the item in a tag 40 | let reverse_element=Regex::new(r#"<\s*?\w+?\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?reverseString.*?>"#).unwrap(); 41 | 42 | //shorten number from 1000 to 1K 43 | let number_shorter=Regex::new(r#"<\s*?\w+?\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?shortenNum.*?>"#).unwrap(); 44 | 45 | //write input to html tag onchange 46 | let write_to_tag=Regex::new(r#"<\s*?\w+?\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?onChange=\s*?(\w+).*?>"#).unwrap(); 47 | 48 | //get all inputs in a form 49 | let form_inputs=Regex::new(r#"<\s*?\w+?\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?submitForm\s*?\[(.+?)\]\s*?=\s*?(\w+).*?>"#).unwrap(); 50 | 51 | //share button with page url as default 52 | let share_link_default=Regex::new(r#"<\s*?a\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?shareDefault=\s*?["|']\s*?(\w+)\s*?["|'].*?>"#).unwrap(); 53 | 54 | //share button with custom url 55 | let share_link_custom=Regex::new(r#"<\s*?a\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?shareCustome\s*?\[\s*?(.*?)\s*?\]\s*?=\s*?["|']\s*?(\w+)\s*?["|'].*?>"#).unwrap(); 56 | 57 | //click to copy 58 | let copy_text=Regex::new(r#"<\s*?\w+?\s*?id=\s*?["|']\s*?(\w+)\s*?["|']\s*?copyArea=\s*?(\w+).*?>"#).unwrap(); 59 | 60 | 61 | //vector to store result 62 | let mut js_vector=vec![]; 63 | 64 | for val in inner_html.captures_iter(value){ 65 | js_vector.push(format!("let {}= document.getElementById(\"{}\").innerHTML;\n", val.get(2).unwrap().as_str(), val.get(1).unwrap().as_str())); 66 | } 67 | 68 | for val in form_value.captures_iter(value){ 69 | js_vector.push(format!("let {}=document.getElementById(\"{}\").value;\n", val.get(2).unwrap().as_str(), val.get(1).unwrap().as_str())); 70 | } 71 | 72 | for val in append_text.captures_iter(value){ 73 | js_vector.push(format!("document.getElementById(\"{}\").innerHTML={};\n", val.get(1).unwrap().as_str(), val.get(2).unwrap().as_str())) 74 | } 75 | 76 | for val2 in limit_size.captures_iter(value){ 77 | js_vector.push(format!("document.getElementById(\"{}\").innerHTML= document.getElementById(\"{}\").innerHTML.substring(0, {});\n", val2.get(1).unwrap().as_str(), val2.get(1).unwrap().as_str(), val2.get(2).unwrap().as_str())) 78 | } 79 | 80 | 81 | for val in form_disable.captures_iter(value){ 82 | js_vector.push(format!("document.getElementById(\"{}\").disabled=true;\n", val.get(1).unwrap().as_str())); 83 | } 84 | 85 | for val in events.captures_iter(value){ 86 | //valid event listeners inclide: click, abort, change, animationstart, canplay, copy, dbclick, drag, drop, fullscreenchange, hashchange, input 87 | //keydown, keypress, keyup, message, mousedown, mousemove, offline, online, pagehide, paste, pause, play, playing, scroll, 88 | //search, seeking, seeked, select, volumechange 89 | if val.get(2).unwrap().as_str()=="click"||val.get(2).unwrap().as_str()=="abort"||val.get(2).unwrap().as_str()=="change"||val.get(2).unwrap().as_str()=="animationstart"|| 90 | val.get(2).unwrap().as_str()=="canplay"||val.get(2).unwrap().as_str()=="copy"||val.get(2).unwrap().as_str()=="dbclick"||val.get(2).unwrap().as_str()=="drag"||val.get(2).unwrap().as_str()=="drop" 91 | ||val.get(2).unwrap().as_str()=="fullscreenchange"||val.get(2).unwrap().as_str()=="hashchange"||val.get(2).unwrap().as_str()=="input"||val.get(2).unwrap().as_str()=="keydown"|| 92 | val.get(2).unwrap().as_str()=="keypress"||val.get(2).unwrap().as_str()=="keyup"||val.get(2).unwrap().as_str()=="message"||val.get(2).unwrap().as_str()=="mouseover"||val.get(2).unwrap().as_str()=="mousedown"|| 93 | val.get(2).unwrap().as_str()=="offline"||val.get(2).unwrap().as_str()=="online"||val.get(2).unwrap().as_str()=="pagehide"||val.get(2).unwrap().as_str()=="paste"||val.get(2).unwrap().as_str()=="pause"||val.get(2).unwrap().as_str()=="play"|| 94 | val.get(2).unwrap().as_str()=="playing"||val.get(2).unwrap().as_str()=="scroll"||val.get(2).unwrap().as_str()=="search"||val.get(2).unwrap().as_str()=="seeking"||val.get(2).unwrap().as_str()=="seeked"|| 95 | val.get(2).unwrap().as_str()=="select"||val.get(2).unwrap().as_str()=="volumechange"{ 96 | js_vector.push(format!("document.getElementById(\"{}\").addEventListener(\"{}\", ()=>{{\n{} }});\n", val.get(1).unwrap().as_str(), val.get(2).unwrap().as_str(), val.get(3).unwrap().as_str())); 97 | }else{ 98 | panic!("unrecognized expression {} valid opions for event listeners include: click, abort, change, animationstart, canplay, copy, dbclick, drag, drop, fullscreenchange, hashchange, input, keydown, keypress, keyup, message, mousedown, mousemove, offline, online, pagehide, paste, pause, play, playing, scroll, search, seeking, seeked, select, volumechange ", val.get(2).unwrap().as_str()) ; 99 | } 100 | } 101 | 102 | for val in format_int.captures_iter(value){ 103 | js_vector.push(format!("document.getElementById(\"{}\").innerHTML= Intl.NumberFormat().format(parseInt(document.getElementById(\"{}\").innerHTML));\n", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())); 104 | } 105 | 106 | for val in format_float.captures_iter(value){ 107 | js_vector.push(format!("document.getElementById(\"{}\").innerHTML= Intl.NumberFormat().format(parseFloat(document.getElementById(\"{}\").innerHTML));\n", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())); 108 | } 109 | 110 | for val in format_currency.captures_iter(value){ 111 | match val.get(2).unwrap().as_str(){ 112 | "dollar"=>{ 113 | js_vector.push(format!("document.getElementById(\"{}\").innerHTML='$'+ Intl.NumberFormat().format(parseFloat(document.getElementById(\"{}\").innerHTML));\n", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())); 114 | }, 115 | "pounds"=>{ 116 | js_vector.push(format!("document.getElementById(\"{}\").innerHTML='£'+ Intl.NumberFormat().format(parseFloat(document.getElementById(\"{}\").innerHTML));\n", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())); 117 | }, 118 | "naira"=>{ 119 | js_vector.push(format!("document.getElementById(\"{}\").innerHTML='₦'+ Intl.NumberFormat().format(parseFloat(document.getElementById(\"{}\").innerHTML));\n", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())); 120 | }, 121 | "yen"=>{ 122 | js_vector.push(format!("document.getElementById(\"{}\").innerHTML='¥'+ Intl.NumberFormat().format(parseFloat(document.getElementById(\"{}\").innerHTML));\n", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())); 123 | }, 124 | "euro"=>{ 125 | js_vector.push(format!("document.getElementById(\"{}\").innerHTML='€'+ Intl.NumberFormat().format(parseFloat(document.getElementById(\"{}\").innerHTML));\n", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())); 126 | }, 127 | "franc"=>{ 128 | js_vector.push(format!("document.getElementById(\"{}\").innerHTML='₣'+ Intl.NumberFormat().format(parseFloat(document.getElementById(\"{}\").innerHTML));\n", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())); 129 | } 130 | _=>{ 131 | panic!("invalid currency {}. Valid currency include : dollar, pounds, naira, yen, euro, and franc", val.get(2).unwrap().as_str()) 132 | } 133 | } 134 | } 135 | 136 | for val in visibility.captures_iter(value){ 137 | //permitted values include: hidden, collapse, visible, initial, inherit 138 | if val.get(2).unwrap().as_str()=="hidden" || val.get(2).unwrap().as_str()=="collapse"||val.get(2).unwrap().as_str()=="visible"|| 139 | val.get(2).unwrap().as_str()=="initial"||val.get(2).unwrap().as_str()=="inherit"{ 140 | js_vector.push(format!("document.getElementById(\"{}\").style.visibility = \"{}\";\n", val.get(1).unwrap().as_str(), val.get(2).unwrap().as_str())); 141 | }else { 142 | panic!("unrecognized expression {} valid options to use with visibility include: hidden, collapse, visible, initial, inherit", val.get(2).unwrap().as_str()); 143 | } 144 | } 145 | 146 | if time_age_format.is_match(value){ 147 | js_vector.push(format!("function timeAgo(date) {{ 148 | 149 | var seconds = Math.floor((new Date() - date) / 1000); 150 | 151 | var interval = Math.floor(seconds / 31536000); 152 | 153 | if (interval > 1) {{ 154 | return interval + ' years ago'; 155 | }} 156 | interval = Math.floor(seconds / 2592000); 157 | if (interval > 1) {{ 158 | return interval + ' months ago'; 159 | }} 160 | interval = Math.floor(seconds / 86400); 161 | if (interval > 1) {{ 162 | return interval + ' days ago'; 163 | }} 164 | interval = Math.floor(seconds / 3600); 165 | if (interval > 1) {{ 166 | return interval + ' hours ago'; 167 | }} 168 | interval = Math.floor(seconds / 60); 169 | if (interval > 1) {{ 170 | return interval + ' minutes ago'; 171 | }} 172 | return Math.floor(seconds) + ' seconds ago'; 173 | }}\n")) 174 | } 175 | 176 | for val in time_age_format.captures_iter(value){ 177 | js_vector.push(format!("document.getElementById('{}').innerHTML=timeAgo(new Date(document.getElementById('{}').innerHTML).getTime())\n", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())) 178 | } 179 | 180 | for val in date_format.captures_iter(value){ 181 | match val.get(2).unwrap().as_str(){ 182 | "dd/mm/yyyy"=>{ 183 | js_vector.push(format!("document.getElementById(\"{}\").innerHTML= new Date(Date.parse(document.getElementById(\"{}\").innerHTML)).getDate()+'/'+parseInt(new Date(Date.parse(document.getElementById(\"{}\").innerHTML)).getMonth()+1) +'/'+new Date(Date.parse(document.getElementById(\"{}\").innerHTML)).getFullYear()\n", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())) 184 | }, 185 | "mm/dd/yyyy"=>{ 186 | js_vector.push(format!("document.getElementById(\"{}\").innerHTML= parseInt(new Date(Date.parse(document.getElementById(\"{}\").innerHTML)).getMonth()+1)+'/' + new Date(Date.parse(document.getElementById(\"{}\").innerHTML)).getDate()+'/'+new Date(Date.parse(document.getElementById(\"{}\").innerHTML)).getFullYear()\n", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())) 187 | }, 188 | "yyyy/mm/dd"=>{ 189 | js_vector.push(format!("document.getElementById(\"{}\").innerHTML= new Date(Date.parse(document.getElementById(\"{}\").innerHTML)).getFullYear()+ '/'+ parseInt(new Date(Date.parse(document.getElementById(\"{}\").innerHTML)).getMonth()+1) +'/'+ new Date(Date.parse(document.getElementById(\"{}\").innerHTML)).getDate()\n", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())) 190 | }, 191 | _=>{ 192 | panic!("invalid date format {} valid formats include: dd/mm/yyyy, mm/dd/yyyy, yyyy/mm/dd", val.get(2).unwrap().as_str()); 193 | } 194 | } 195 | } 196 | 197 | 198 | for val in reverse_element.captures_iter(value){ 199 | js_vector.push(format!("document.getElementById('{}').innerHTML= document.getElementById('{}').innerHTML.split(' ').reverse().join(' ')\n", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())) 200 | } 201 | if number_shorter.is_match(value){ 202 | js_vector.push(format!("function NumFormatter(num) {{ 203 | if(Math.abs(num) < 999){{ 204 | return Math.sign(num)*Math.abs(num) 205 | }}else if(Math.abs(num) > 999 && Math.abs(num) < 1000000){{ 206 | return Math.sign(num)*((Math.abs(num)/1000).toFixed(2)) + 'k' 207 | }}else if(Math.abs(num) > 999999 && Math.abs(num) < 1000000000) 208 | {{ 209 | return Math.sign(num)*((Math.abs(num)/1000000).toFixed(2)) + 'M' 210 | }}else if(Math.abs(num) > 999999999 && Math.abs(num) < 1000000000000){{ 211 | return Math.sign(num)*((Math.abs(num)/1000000000).toFixed(2)) + 'B' 212 | }}else if(Math.abs(num) > 999999999999 && Math.abs(num) < 1000000000000000){{ 213 | return Math.sign(num)*((Math.abs(num)/1000000000000).toFixed(2)) + 'T' 214 | }} 215 | }}\n")); 216 | } 217 | 218 | for val in number_shorter.captures_iter(value){ 219 | js_vector.push(format!("document.getElementById('{}').innerHTML=NumFormatter(parseInt(document.getElementById('{}').innerHTML))\n", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())) 220 | } 221 | 222 | for val in write_to_tag.captures_iter(value){ 223 | js_vector.push(format!("document.getElementById('{}').addEventListener('input', (event)=>{{ 224 | document.getElementById('{}').innerHTML=event.target.value 225 | }})\n", val.get(1).unwrap().as_str(), val.get(2).unwrap().as_str())) 226 | } 227 | 228 | if form_inputs.is_match(value){ 229 | js_vector.push(format!("function getForm(form){{ 230 | var elements = document.getElementById(form).elements; 231 | var obj ={{}}; 232 | for(var i = 0 ; i < elements.length ; i++){{ 233 | var item = elements.item(i); 234 | obj[item.name] = item.value; 235 | if(obj[item.name]==''){{ 236 | delete obj[item.name]; 237 | }} 238 | }} 239 | return obj 240 | }}\n")) 241 | } 242 | 243 | for val in form_inputs.captures_iter(value){ 244 | js_vector.push(format!("document.getElementById('{}').addEventListener('click', (event)=>{{ 245 | event.preventDefault(); 246 | fetch('{}', {{ 247 | method: 'POST', 248 | headers: {{ 249 | 'Content-Type': 'application/json' 250 | }}, 251 | body:JSON.stringify(getForm('{}')) 252 | }}).then((res) => res.json()) 253 | .then((data) => console.log(data)) 254 | .catch((err)=>console.log(err)) 255 | }})\n", val.get(1).unwrap().as_str(), val.get(2).unwrap().as_str(), val.get(3).unwrap().as_str())) 256 | } 257 | 258 | if share_link_default.is_match(value){ 259 | js_vector.push(format!("var pageUrl=window.location.href;")) 260 | } 261 | 262 | for val in share_link_default.captures_iter(value){ 263 | match val.get(2).unwrap().as_str() { 264 | "facebook" => { 265 | js_vector.push(format!("var {} = document.getElementById('{}'); 266 | {}.href='https://www.facebook.com/sharer.php?u='+pageUrl; 267 | document.body.appendChild({})\n; 268 | ", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())) 269 | }, 270 | "twitter"=>{ 271 | js_vector.push(format!("var {} = document.getElementById('{}'); 272 | {}.href='https://twitter.com/intent/tweet?url='+pageUrl; 273 | document.body.appendChild({})\n; 274 | ", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())) 275 | }, 276 | "linkedin"=>{ 277 | js_vector.push(format!("var {} = document.getElementById('{}'); 278 | {}.href='https://www.linkedin.com/shareArticle?mini=true&url='+pageUrl; 279 | document.body.appendChild({})\n; 280 | ", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())) 281 | }, 282 | "whatsapp"=>{ 283 | js_vector.push(format!("var {} = document.getElementById('{}'); 284 | {}.href='https://api.whatsapp.com/send?text='+pageUrl; 285 | document.body.appendChild({})\n; 286 | ", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())) 287 | }, 288 | "reddit"=>{ 289 | js_vector.push(format!("var {} = document.getElementById('{}'); 290 | {}.href='http://www.reddit.com/submit?url='+pageUrl; 291 | document.body.appendChild({})\n; 292 | ", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())) 293 | }, 294 | "telegram"=>{ 295 | js_vector.push(format!("var {} = document.getElementById('{}'); 296 | {}.href='https://t.me/share/url?url='+pageUrl; 297 | document.body.appendChild({})\n; 298 | ", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str())) 299 | 300 | }, 301 | _ => { 302 | panic!("unrecognized option {} valid options include facebook, twitter, linkedin, whatsapp, telegram and reddit", val.get(2).unwrap().as_str()) 303 | } 304 | } 305 | } 306 | 307 | for val in share_link_custom.captures_iter(value){ 308 | match val.get(3).unwrap().as_str() { 309 | "facebook" => { 310 | js_vector.push(format!("var {} = document.getElementById('{}'); 311 | {}.href='https://www.facebook.com/sharer.php?u='+'{}'; 312 | document.body.appendChild({})\n; 313 | ", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(2).unwrap().as_str(), val.get(1).unwrap().as_str())) 314 | }, 315 | "twitter"=>{ 316 | js_vector.push(format!("var {} = document.getElementById('{}'); 317 | {}.href='https://twitter.com/intent/tweet?url='+'{}'; 318 | document.body.appendChild({})\n; 319 | ", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(2).unwrap().as_str(), val.get(1).unwrap().as_str())) 320 | }, 321 | "linkedin"=>{ 322 | js_vector.push(format!("var {} = document.getElementById('{}'); 323 | {}.href='https://www.linkedin.com/shareArticle?mini=true&url='+'{}'; 324 | document.body.appendChild({})\n; 325 | ", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(2).unwrap().as_str(), val.get(1).unwrap().as_str())) 326 | }, 327 | "whatsapp"=>{ 328 | js_vector.push(format!("var {} = document.getElementById('{}'); 329 | {}.href='https://api.whatsapp.com/send?text='+'{}'; 330 | document.body.appendChild({})\n; 331 | ", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(2).unwrap().as_str(), val.get(1).unwrap().as_str())) 332 | }, 333 | "reddit"=>{ 334 | js_vector.push(format!("var {} = document.getElementById('{}'); 335 | {}.href='http://www.reddit.com/submit?url='+'{}'; 336 | document.body.appendChild({})\n; 337 | ", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(2).unwrap().as_str(), val.get(1).unwrap().as_str())) 338 | }, 339 | "telegram"=>{ 340 | js_vector.push(format!("var {} = document.getElementById('{}'); 341 | {}.href='https://t.me/share/url?url='+'{}'; 342 | document.body.appendChild({})\n; 343 | ", val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(1).unwrap().as_str(), val.get(2).unwrap().as_str(), val.get(1).unwrap().as_str())) 344 | 345 | }, 346 | _ => { 347 | panic!("unrecognized option {} valid options include facebook, twitter, linkedin, whatsapp and reddit", val.get(2).unwrap().as_str()) 348 | } 349 | } 350 | } 351 | 352 | if copy_text.is_match(value){ 353 | js_vector.push(format!("function copyToClip(id){{ 354 | var copyText = document.getElementById(id); 355 | var textArea = document.createElement('textarea'); 356 | textArea.value = copyText.textContent; 357 | document.body.appendChild(textArea); 358 | textArea.select(); 359 | document.execCommand('Copy'); 360 | textArea.remove(); 361 | }}\n")) 362 | } 363 | 364 | for val in copy_text.captures_iter(value){ 365 | js_vector.push(format!("document.getElementById('{}').addEventListener('click', (e)=>{{ 366 | e.preventDefault(); 367 | copyToClip('{}') 368 | }})\n", val.get(1).unwrap().as_str(), val.get(2).unwrap().as_str())) 369 | } 370 | js_vector 371 | } 372 | 373 | } 374 | --------------------------------------------------------------------------------