neutralts/
constants.rs

1use lazy_static::lazy_static;
2use std::collections::HashMap;
3use std::env;
4
5/// neutralts version
6pub const VERSION: &str = env!("CARGO_PKG_VERSION");
7
8///  Bif delimiters
9///
10/// ```text
11///   .------------------------------> BIF_OPEN = { + BIF_DELIM
12///   |.-----------------------------> BIF_DELIM
13///   ||.----------------------------> BIF_MOD_... (Modifiers)
14///   |||       .--------------------> BIF_NAME
15///   |||       |    .---------------> BIF_ARRAY
16///   |||       |    ||    .---------> BIF_CODE
17///   |||       |    ||    ||      .-> BIF_CLOSE = BIF_DELIM + }
18///   |||       |    ||    ||      |
19///   vvv       v    vv    vv      v
20///   {:!snippet; var->key >> ... :}
21/// ```
22pub const BIF_DELIM: &str = ":";
23
24///  Bif delimiters
25///
26/// ```text
27///   .------------------------------> BIF_OPEN = { + BIF_DELIM
28///   |.-----------------------------> BIF_DELIM
29///   ||.----------------------------> BIF_MOD_... (Modifiers)
30///   |||       .--------------------> BIF_NAME
31///   |||       |    .---------------> BIF_ARRAY
32///   |||       |    ||    .---------> BIF_CODE
33///   |||       |    ||    ||      .-> BIF_CLOSE = BIF_DELIM + }
34///   |||       |    ||    ||      |
35///   vvv       v    vv    vv      v
36///   {:!snippet; var->key >> ... :}
37/// ```
38pub const BIF_OPEN: &str = "{:";
39
40///  Bif delimiters
41///
42/// ```text
43///   .------------------------------> BIF_OPEN = { + BIF_DELIM
44///   |.-----------------------------> BIF_DELIM
45///   ||.----------------------------> BIF_MOD_... (Modifiers)
46///   |||       .--------------------> BIF_NAME
47///   |||       |    .---------------> BIF_ARRAY
48///   |||       |    ||    .---------> BIF_CODE
49///   |||       |    ||    ||      .-> BIF_CLOSE = BIF_DELIM + }
50///   |||       |    ||    ||      |
51///   vvv       v    vv    vv      v
52///   {:!snippet; var->key >> ... :}
53/// ```
54pub const BIF_CLOSE: &str = ":}";
55
56///  Bif delimiters
57///
58/// ```text
59///   .------------------------------> BIF_OPEN = { + BIF_DELIM
60///   |.-----------------------------> BIF_DELIM
61///   ||.----------------------------> BIF_MOD_... (Modifiers)
62///   |||       .--------------------> BIF_NAME
63///   |||       |    .---------------> BIF_ARRAY
64///   |||       |    ||    .---------> BIF_CODE
65///   |||       |    ||    ||      .-> BIF_CLOSE = BIF_DELIM + }
66///   |||       |    ||    ||      |
67///   vvv       v    vv    vv      v
68///   {:!snippet; var->key >> ... :}
69/// ```
70pub const BIF_NAME: &str = ";";
71
72///  Bif delimiters
73///
74/// ```text
75///   .------------------------------> BIF_OPEN = { + BIF_DELIM
76///   |.-----------------------------> BIF_DELIM
77///   ||.----------------------------> BIF_MOD_... (Modifiers)
78///   |||       .--------------------> BIF_NAME
79///   |||       |    .---------------> BIF_ARRAY
80///   |||       |    ||    .---------> BIF_CODE
81///   |||       |    ||    ||      .-> BIF_CLOSE = BIF_DELIM + }
82///   |||       |    ||    ||      |
83///   vvv       v    vv    vv      v
84///   {:!snippet; var->key >> ... :}
85/// ```
86pub const BIF_CODE: &str = ">>";
87
88///  Bif delimiters
89///
90/// ```text
91///   .------------------------------> BIF_OPEN = { + BIF_DELIM
92///   |.-----------------------------> BIF_DELIM
93///   ||.----------------------------> BIF_MOD_... (Modifiers)
94///   |||       .--------------------> BIF_NAME
95///   |||       |    .---------------> BIF_ARRAY
96///   |||       |    ||    .---------> BIF_CODE
97///   |||       |    ||    ||      .-> BIF_CLOSE = BIF_DELIM + }
98///   |||       |    ||    ||      |
99///   vvv       v    vv    vv      v
100///   {:!snippet; var->key >> ... :}
101/// ```
102pub const BIF_ARRAY: &str = "->";
103
104///  Bif comment
105///
106/// ```text
107///      .---> BIF_COMMENT
108///     |
109///     v
110///   {:* commnet *:}
111/// ```
112pub const BIF_COMMENT: &str = "*";
113
114///  Bif comment open
115///
116/// ```text
117///   .---> BIF_COMMENT_OPEN
118///   |||
119///   vvv
120///   {:* commnet *:}
121/// ```
122pub const BIF_COMMENT_OPEN: &str = "{:*";
123
124///  Bif comment close
125///
126/// ```text
127///               .---> BIF_COMMENT_CLOSE
128///               |||
129///               vvv
130///   {:* commnet *:}
131/// ```
132pub const BIF_COMMENT_CLOSE: &str = "*:}";
133
134/// modifier filter
135pub const BIF_MOD_FILTER: &str = "&";
136
137/// modifier not
138pub const BIF_MOD_NEGATE: &str = "!";
139
140/// modifier upline
141pub const BIF_MOD_UPLINE: &str = "^";
142
143/// modifier scope
144pub const BIF_MOD_SCOPE: &str = "+";
145
146/// Identify bif var as it has no name
147pub const BIF_VAR: &str = "{:;";
148
149/// delim as bytes
150pub const BIF_DELIM_B: &[u8] = BIF_DELIM.as_bytes();
151
152/// BIF_OPEN as bytes
153pub const BIF_OPEN_B: &[u8] = BIF_OPEN.as_bytes();
154
155/// BIF_OPEN 0 as bytes
156pub const BIF_OPEN0: u8 = BIF_OPEN.as_bytes()[0];
157
158/// BIF_OPEN 1 as bytes
159pub const BIF_OPEN1: u8 = BIF_OPEN.as_bytes()[1];
160
161/// BIF_CLOSE as bytes
162pub const BIF_CLOSE_B: &[u8] = BIF_CLOSE.as_bytes();
163
164/// BIF_CLOSE 0 as bytes
165pub const BIF_CLOSE0: u8 = BIF_CLOSE.as_bytes()[0];
166
167/// BIF_CLOSE 1 as bytes
168pub const BIF_CLOSE1: u8 = BIF_CLOSE.as_bytes()[1];
169
170/// BIF_CODE as bytes
171pub const BIF_CODE_B: &[u8] = BIF_CODE.as_bytes();
172
173/// BIF_COMMENT as bytes
174pub const BIF_COMMENT_B: u8 = BIF_COMMENT.as_bytes()[0];
175
176/// BIF_COMMENT_OPEN as bytes
177pub const BIF_COMMENT_OPEN_B: &[u8] = BIF_COMMENT_OPEN.as_bytes();
178
179/// BIF_COMMENT_CLOSE as bytes
180pub const BIF_COMMENT_CLOSE_B: &[u8] = BIF_COMMENT_CLOSE.as_bytes();
181
182/// replacement for BIF_OPEN sanitation
183pub const BIF_SANITIZE_OPEN: &str = "{:";
184
185/// replacement for BIF_CLOSE sanitation
186pub const BIF_SANITIZE_CLOSE: &str = ":}";
187
188/// html entity for {:;:}
189pub const UNPRINTABLE: &str = "�";
190
191/// html entity for null
192pub const NULL: &str = "�";
193
194/// empty
195pub const EMPTY: &str = "";
196
197/// Empty string could be different in different environments and could be an
198/// HTM entity. It is also used to make it clear that it is an empty string.
199pub const EMPTY_STRING: String = String::new();
200
201/// html entity for space
202pub const SPACE: &str = " ";
203
204/// html entity for crlf
205pub const CRLF: &str = "
";
206
207/// html entity for Backspace
208pub const BACKSPACE: &str = "&#9224";
209
210/// false
211pub const FALSE: bool = false;
212
213/// true
214pub const TRUE: bool = true;
215
216/// Identify bif allow
217pub const BIF_ALLOWED: [&str; 2] = ["{:allow;", "{:!allow;"];
218
219/// To detect the template files that may contain snippet
220pub const SNIPPETS_FILES: &str = "snippet";
221
222/// bif list
223pub const BIF_LIST: [&str; 36] = [
224    "", "allow", "array", "bool", "cache", "coalesce", "code", "contains", "count", "data", "date",
225    "declare", "defined", "each", "else", "eval", "exit", "fetch", "filled", "flg", "for", "hash",
226    "include", "join", "lang", "locale", "moveto", "neutral", "param", "rand", "redirect",
227    "replace", "same", "snippet", "sum", "trans",
228];
229
230/// bif alias list because some bifs have no name
231pub const BIF_ALIAS_LIST: [&str; 37] = [
232    "allow",
233    "array",
234    "bool",
235    "cache",
236    "coalesce",
237    "code",
238    "contains",
239    "count",
240    "data",
241    "date",
242    "declare",
243    "defined",
244    "each",
245    "else",
246    "eval",
247    "exit",
248    "fetch",
249    "filled",
250    "flg",
251    "for",
252    "hash",
253    "include",
254    "join",
255    "lang",
256    "locale",
257    "moveto",
258    "neutral",
259    "param",
260    "rand",
261    "redirect",
262    "replace",
263    "same",
264    "snippet",
265    "sum",
266    "trans",
267    "unprintable",
268    "var",
269];
270
271lazy_static! {
272    /// HTTP status codes
273    pub static ref STATUS_CODES: HashMap<&'static str, &'static str> = {
274        let mut m = HashMap::new();
275        m.insert("100", "Continue");
276        m.insert("101", "Switching Protocols");
277        m.insert("103", "Early Hints");
278        m.insert("200", "OK");
279        m.insert("201", "Created");
280        m.insert("202", "Accepted");
281        m.insert("203", "Non-Authoritative Information");
282        m.insert("204", "No Content");
283        m.insert("205", "Reset Content");
284        m.insert("206", "Partial Content");
285        m.insert("208", "Already Reported");
286        m.insert("226", "IM Used");
287        m.insert("300", "Multiple Choices");
288        m.insert("301", "Moved Permanently");
289        m.insert("302", "Found");
290        m.insert("303", "See Other");
291        m.insert("304", "Not Modified");
292        m.insert("305", "Use Proxy");
293        m.insert("306", "Switch Proxy"); // old http version
294        m.insert("307", "Temporary Redirect");
295        m.insert("308", "Permanent Redirect");
296        m.insert("400", "Bad Request");
297        m.insert("401", "Unauthorized");
298        m.insert("402", "Payment Required");
299        m.insert("403", "Forbidden");
300        m.insert("404", "Not Found");
301        m.insert("405", "Method Not Allowed");
302        m.insert("406", "Not Acceptable");
303        m.insert("407", "Proxy Authentication Required");
304        m.insert("408", "Request Time-out");
305        m.insert("409", "Conflict");
306        m.insert("410", "Gone");
307        m.insert("411", "Length Required");
308        m.insert("412", "Precondition Failed");
309        m.insert("413", "Payload Too Large");
310        m.insert("414", "URI Too Long");
311        m.insert("415", "Unsupported Media Type");
312        m.insert("416", "Range Not Satisfiable");
313        m.insert("417", "Expectation Failed");
314        m.insert("421", "Misdirected Request");
315        m.insert("422", "Unprocessable Entity");
316        m.insert("423", "Locked");
317        m.insert("424", "Failed Dependency");
318        m.insert("425", "Too Early");
319        m.insert("426", "Upgrade Required");
320        m.insert("428", "Precondition Required");
321        m.insert("429", "Too Many Requests");
322        m.insert("431", "Request Header Fields Too Large");
323        m.insert("451", "Unavailable For Legal Reasons");
324        m.insert("500", "Internal Server Error");
325        m.insert("501", "Not Implemented");
326        m.insert("502", "Bad Gateway");
327        m.insert("503", "Service Unavailable");
328        m.insert("504", "Gateway Time-out");
329        m.insert("505", "HTTP Version Not Supported");
330        m.insert("506", "Variant Also Negotiates (Experimental)");
331        m.insert("510", "Not Extended");
332        m.insert("511", "Network Authentication Required");
333
334        m
335    };
336}
337
338/// JavaScript script reloads the current top page, used in {:redirect;
339pub const REDIR_JS_RELOAD_TOP: &str =
340    "<!DOCTYPE html><script>top.location.href=self.location.href.split('#')[0];</script>";
341
342/// JavaScript script reloads the current, used in {:redirect;
343pub const REDIR_JS_RELOAD_SELF: &str =
344    "<!DOCTYPE html><script>self.location.href=self.location.href.split('#')[0]</script>";
345
346/// JavaScript script that redirects to a new URL in the top page, used in {:redirect;
347/// The placeholder '{}' should be replaced with the destination url.
348pub const REDIR_JS_REDIRECT_TOP: &str = "<!DOCTYPE html><script>top.location.href='{}';</script>";
349
350/// JavaScript script that redirects to a new URL in the self page, used in {:redirect;
351/// The placeholder '{}' should be replaced with the destination url.
352pub const REDIR_JS_REDIRECT_SELF: &str = "<!DOCTYPE html><script>self.location.href='{}';</script>";
353
354lazy_static! {
355    /// JavaScript for {:fetch; ... :}
356    pub static ref NEUTRAL_JS: String = r#"<script>{
357        const d=document;
358        let sl='...';
359        let sd=250;
360        let st=30000;
361        let se=' Form ERROR! ';
362        let sed=3500;
363        "undefined"!=typeof neutral_submit_loading&&(sl=neutral_submit_loading);
364        "undefined"!=typeof neutral_submit_delay&&(sd=neutral_submit_delay);
365        "undefined"!=typeof neutral_submit_timeout&&(st=neutral_submit_timeout);
366        "undefined"!=typeof neutral_submit_error&&(se=neutral_submit_error);
367        "undefined"!=typeof neutral_submit_error_delay&&(sed=neutral_submit_error_delay);
368
369        const o=new IntersectionObserver((e)=>{
370            e.forEach(e=>{
371                if(e.isIntersecting){
372                    o.unobserve(e.target);
373                    neutral_fetch(e.target,e.target.dataset.url,e.target.dataset.wrap);
374                }
375            });
376        });
377
378        function neutral_obs(){
379            d.querySelectorAll('.neutral-fetch-visible').forEach((e)=>{
380                e.classList.remove('neutral-fetch-visible');
381                o.observe(e);
382            });
383        }
384
385        function neutral_fetch(e,u,w){
386            let h=e;if(w){h=d.getElementById(w)}
387            fetch(u,{headers:{'requested-with-ajax':'fetch'}})
388            .then(response=>response.text())
389            .then(html=>{
390                h.innerHTML=html;
391                h.outerHTML=html;
392                window.dispatchEvent(new CustomEvent('neutralFetchCompleted',{detail:{element:h,url:u}}));
393            })
394            .catch(error=>{
395                h.innerHTML=se;
396                window.dispatchEvent(new CustomEvent('neutralFetchError',{detail:{element:h,url:u}}));
397            });
398        }
399
400        function neutral_fetch_form(f,u,w){
401            const subs = f.querySelectorAll('[type=submit]');
402            subs.forEach((e)=>{
403                e.disabled=true;
404                e.dataset['restsubs']=e.innerHTML;
405                e.innerHTML=e.innerHTML + ' ' + sl;
406            });
407            let h=f;if(w){h = d.getElementById(w)}
408            let dt=new FormData(f);
409            let has_file=false;
410            for(let i=0;i<f.elements.length;i++){
411                value=f.elements[i].value;
412                if(f.elements[i].name===""){
413                    continue;
414                }
415                if(f.elements[i].type=="file"){
416                    has_file=true;
417                    continue;
418                }
419                if(f.elements[i].name.indexOf('[]')>=0){
420                    continue;
421                }
422                if(f.elements[i].type=="checkbox" || f.elements[i].type=="radio"){
423                    if(!f.elements[i].checked){
424                        continue;
425                    }
426                }
427                dt.append(f.elements[i].name,value);
428            }
429            if(!has_file){dt=new URLSearchParams(new FormData(f))}
430            setTimeout(()=>{
431                fetch(u,{
432                    signal:AbortSignal.timeout(st),
433                    method:'POST',
434                    headers:{'requested-with-ajax':'fetch'},
435                    body:dt,
436                })
437                .then(response=>response.text())
438                .then(html=>{
439                    h.innerHTML=html;
440                    h.outerHTML=html;
441                    window.dispatchEvent(new CustomEvent('neutralFetchCompleted',{detail:{element:h,url:u}}));
442                })
443                .catch(error=>{
444                    window.dispatchEvent(new CustomEvent('neutralFetchError',{detail:{element:h,url:u}}));
445                    subs.forEach((e)=>{e.disabled=true;e.innerHTML=se;});
446                    setTimeout(()=>{
447                        subs.forEach((e)=>{e.disabled=false;e.innerHTML=e.dataset['restsubs']});
448                    },sed);
449                });
450            },sd);
451        }
452
453        function neutral_fev(){
454            d.querySelectorAll('.neutral-fetch-form').forEach((e)=>{
455                e.classList.remove('neutral-fetch-form');
456                function handleSubmit(ev){
457                    ev.preventDefault();
458                    neutral_fetch_form(e,e.getAttribute('action'),e.dataset.wrap);
459                }
460                e.addEventListener('submit',handleSubmit);
461            });
462
463            d.querySelectorAll('.neutral-fetch-auto').forEach((e)=>{
464                e.classList.remove('neutral-fetch-auto');
465                neutral_fetch(e,e.dataset.url,e.dataset.wrap);
466            });
467
468            d.querySelectorAll('.neutral-fetch-click').forEach((e)=>{
469                e.classList.remove('neutral-fetch-click');
470                function handleClick(){
471                    neutral_fetch(e,e.dataset.url,e.dataset.wrap);
472                }
473                e.addEventListener('click',handleClick);
474            });
475            neutral_obs();
476        }
477
478        d.addEventListener('DOMContentLoaded',()=>{
479            neutral_fev();
480        });
481        window.addEventListener('neutralFetchCompleted',()=>{
482            neutral_fev();
483        });
484        window.addEventListener('neutralFetchError',()=>{
485            neutral_fev();
486        });
487    }</script>"#.replace("\n", "").replace("  ", "");
488}
489
490/// HTML container form for {:fetch; ... :}
491pub const DIV_FETCH_FORM: &str = r#"
492<form id="{id}" name="{name}" class="neutral-fetch-form {class}" method="POST" action="{endpoint}" data-wrap="{wrap}">
493    {body}
494</form>
495"#;
496
497/// HTML container none for {:fetch; ... :}
498pub const DIV_FETCH_NONE: &str = r#"
499<div id="{id}" class="neutral-fetch-none {class}" data-url="{endpoint}" data-wrap="{wrap}">
500    {body}
501</div>
502"#;
503
504/// HTML container auto for {:fetch; ... :}
505pub const DIV_FETCH_AUTO: &str = r#"
506<div id="{id}" class="neutral-fetch-auto {class}" data-url="{endpoint}" data-wrap="{wrap}">
507    {body}
508</div>
509"#;
510
511/// HTML container visible for {:fetch; ... :}
512pub const DIV_FETCH_VISIBLE: &str = r#"
513<div id="{id}" class="neutral-fetch-visible {class}" data-url="{endpoint}" data-wrap="{wrap}">
514    {body}
515</div>
516"#;
517
518/// HTML container click for {:fetch; ... :}
519pub const DIV_FETCH_CLICK: &str = r#"
520<div id="{id}" class="neutral-fetch-click {class}" data-url="{endpoint}" data-wrap="{wrap}">
521    {body}
522</div>
523"#;
524
525pub const DEFAULT_OBJ_ENGINE: &str = "python";
526pub const DEFAULT_OBJ_CALLBACK: &str = "main";