Actualizacion maquina principal
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / uri-js / src / schemes / mailto.ts
1 import { URISchemeHandler, URIComponents, URIOptions } from "../uri";
2 import { pctEncChar, pctDecChars, unescapeComponent } from "../uri";
3 import punycode from "punycode";
4 import { merge, subexp, toUpperCase, toArray } from "../util";
5
6 export interface MailtoHeaders {
7         [hfname:string]:string
8 }
9
10 export interface MailtoComponents extends URIComponents {
11         to:Array<string>,
12         headers?:MailtoHeaders,
13         subject?:string,
14         body?:string
15 }
16
17 const O:MailtoHeaders = {};
18 const isIRI = true;
19
20 //RFC 3986
21 const UNRESERVED$$ = "[A-Za-z0-9\\-\\.\\_\\~" + (isIRI ? "\\xA0-\\u200D\\u2010-\\u2029\\u202F-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF" : "") + "]";
22 const HEXDIG$$ = "[0-9A-Fa-f]";  //case-insensitive
23 const PCT_ENCODED$ = subexp(subexp("%[EFef]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + subexp("%[89A-Fa-f]" + HEXDIG$$ + "%" + HEXDIG$$ + HEXDIG$$) + "|" + subexp("%" + HEXDIG$$ + HEXDIG$$));  //expanded
24
25 //RFC 5322, except these symbols as per RFC 6068: @ : / ? # [ ] & ; =
26 //const ATEXT$$ = "[A-Za-z0-9\\!\\#\\$\\%\\&\\'\\*\\+\\-\\/\\=\\?\\^\\_\\`\\{\\|\\}\\~]";
27 //const WSP$$ = "[\\x20\\x09]";
28 //const OBS_QTEXT$$ = "[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]";  //(%d1-8 / %d11-12 / %d14-31 / %d127)
29 //const QTEXT$$ = merge("[\\x21\\x23-\\x5B\\x5D-\\x7E]", OBS_QTEXT$$);  //%d33 / %d35-91 / %d93-126 / obs-qtext
30 //const VCHAR$$ = "[\\x21-\\x7E]";
31 //const WSP$$ = "[\\x20\\x09]";
32 //const OBS_QP$ = subexp("\\\\" + merge("[\\x00\\x0D\\x0A]", OBS_QTEXT$$));  //%d0 / CR / LF / obs-qtext
33 //const FWS$ = subexp(subexp(WSP$$ + "*" + "\\x0D\\x0A") + "?" + WSP$$ + "+");
34 //const QUOTED_PAIR$ = subexp(subexp("\\\\" + subexp(VCHAR$$ + "|" + WSP$$)) + "|" + OBS_QP$);
35 //const QUOTED_STRING$ = subexp('\\"' + subexp(FWS$ + "?" + QCONTENT$) + "*" + FWS$ + "?" + '\\"');
36 const ATEXT$$ = "[A-Za-z0-9\\!\\$\\%\\'\\*\\+\\-\\^\\_\\`\\{\\|\\}\\~]";
37 const QTEXT$$ = "[\\!\\$\\%\\'\\(\\)\\*\\+\\,\\-\\.0-9\\<\\>A-Z\\x5E-\\x7E]";
38 const VCHAR$$ = merge(QTEXT$$, "[\\\"\\\\]");
39 const DOT_ATOM_TEXT$ = subexp(ATEXT$$ + "+" + subexp("\\." + ATEXT$$ + "+") + "*");
40 const QUOTED_PAIR$ = subexp("\\\\" + VCHAR$$);
41 const QCONTENT$ = subexp(QTEXT$$ + "|" + QUOTED_PAIR$);
42 const QUOTED_STRING$ = subexp('\\"' + QCONTENT$ + "*" + '\\"');
43
44 //RFC 6068
45 const DTEXT_NO_OBS$$ = "[\\x21-\\x5A\\x5E-\\x7E]";  //%d33-90 / %d94-126
46 const SOME_DELIMS$$ = "[\\!\\$\\'\\(\\)\\*\\+\\,\\;\\:\\@]";
47 const QCHAR$ = subexp(UNRESERVED$$ + "|" + PCT_ENCODED$ + "|" + SOME_DELIMS$$);
48 const DOMAIN$ = subexp(DOT_ATOM_TEXT$ + "|" + "\\[" + DTEXT_NO_OBS$$ + "*" + "\\]");
49 const LOCAL_PART$ = subexp(DOT_ATOM_TEXT$ + "|" + QUOTED_STRING$);
50 const ADDR_SPEC$ = subexp(LOCAL_PART$ + "\\@" + DOMAIN$);
51 const TO$ = subexp(ADDR_SPEC$ + subexp("\\," + ADDR_SPEC$) + "*");
52 const HFNAME$ = subexp(QCHAR$ + "*");
53 const HFVALUE$ = HFNAME$;
54 const HFIELD$ = subexp(HFNAME$ + "\\=" + HFVALUE$);
55 const HFIELDS2$ = subexp(HFIELD$ + subexp("\\&" + HFIELD$) + "*");
56 const HFIELDS$ = subexp("\\?" + HFIELDS2$);
57 const MAILTO_URI = new RegExp("^mailto\\:" + TO$ + "?" + HFIELDS$ + "?$");
58
59 const UNRESERVED = new RegExp(UNRESERVED$$, "g");
60 const PCT_ENCODED = new RegExp(PCT_ENCODED$, "g");
61 const NOT_LOCAL_PART = new RegExp(merge("[^]", ATEXT$$, "[\\.]", '[\\"]', VCHAR$$), "g");
62 const NOT_DOMAIN = new RegExp(merge("[^]", ATEXT$$, "[\\.]", "[\\[]", DTEXT_NO_OBS$$, "[\\]]"), "g");
63 const NOT_HFNAME = new RegExp(merge("[^]", UNRESERVED$$, SOME_DELIMS$$), "g");
64 const NOT_HFVALUE = NOT_HFNAME;
65 const TO = new RegExp("^" + TO$ + "$");
66 const HFIELDS = new RegExp("^" + HFIELDS2$ + "$");
67
68 function decodeUnreserved(str:string):string {
69         const decStr = pctDecChars(str);
70         return (!decStr.match(UNRESERVED) ? str : decStr);
71 }
72
73 const handler:URISchemeHandler<MailtoComponents> =  {
74         scheme : "mailto",
75
76         parse : function (components:URIComponents, options:URIOptions):MailtoComponents {
77                 const mailtoComponents = components as MailtoComponents;
78                 const to = mailtoComponents.to = (mailtoComponents.path ? mailtoComponents.path.split(",") : []);
79                 mailtoComponents.path = undefined;
80
81                 if (mailtoComponents.query) {
82                         let unknownHeaders = false
83                         const headers:MailtoHeaders = {};
84                         const hfields = mailtoComponents.query.split("&");
85
86                         for (let x = 0, xl = hfields.length; x < xl; ++x) {
87                                 const hfield = hfields[x].split("=");
88
89                                 switch (hfield[0]) {
90                                         case "to":
91                                                 const toAddrs = hfield[1].split(",");
92                                                 for (let x = 0, xl = toAddrs.length; x < xl; ++x) {
93                                                         to.push(toAddrs[x]);
94                                                 }
95                                                 break;
96                                         case "subject":
97                                                 mailtoComponents.subject = unescapeComponent(hfield[1], options);
98                                                 break;
99                                         case "body":
100                                                 mailtoComponents.body = unescapeComponent(hfield[1], options);
101                                                 break;
102                                         default:
103                                                 unknownHeaders = true;
104                                                 headers[unescapeComponent(hfield[0], options)] = unescapeComponent(hfield[1], options);
105                                                 break;
106                                 }
107                         }
108
109                         if (unknownHeaders) mailtoComponents.headers = headers;
110                 }
111
112                 mailtoComponents.query = undefined;
113
114                 for (let x = 0, xl = to.length; x < xl; ++x) {
115                         const addr = to[x].split("@");
116
117                         addr[0] = unescapeComponent(addr[0]);
118
119                         if (!options.unicodeSupport) {
120                                 //convert Unicode IDN -> ASCII IDN
121                                 try {
122                                         addr[1] = punycode.toASCII(unescapeComponent(addr[1], options).toLowerCase());
123                                 } catch (e) {
124                                         mailtoComponents.error = mailtoComponents.error || "Email address's domain name can not be converted to ASCII via punycode: " + e;
125                                 }
126                         } else {
127                                 addr[1] = unescapeComponent(addr[1], options).toLowerCase();
128                         }
129
130                         to[x] = addr.join("@");
131                 }
132
133                 return mailtoComponents;
134         },
135
136         serialize : function (mailtoComponents:MailtoComponents, options:URIOptions):URIComponents {
137                 const components = mailtoComponents as URIComponents;
138                 const to = toArray(mailtoComponents.to);
139                 if (to) {
140                         for (let x = 0, xl = to.length; x < xl; ++x) {
141                                 const toAddr = String(to[x]);
142                                 const atIdx = toAddr.lastIndexOf("@");
143                                 const localPart = (toAddr.slice(0, atIdx)).replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, toUpperCase).replace(NOT_LOCAL_PART, pctEncChar);
144                                 let domain = toAddr.slice(atIdx + 1);
145
146                                 //convert IDN via punycode
147                                 try {
148                                         domain = (!options.iri ? punycode.toASCII(unescapeComponent(domain, options).toLowerCase()) : punycode.toUnicode(domain));
149                                 } catch (e) {
150                                         components.error = components.error || "Email address's domain name can not be converted to " + (!options.iri ? "ASCII" : "Unicode") + " via punycode: " + e;
151                                 }
152
153                                 to[x] = localPart + "@" + domain;
154                         }
155
156                         components.path = to.join(",");
157                 }
158
159                 const headers = mailtoComponents.headers = mailtoComponents.headers || {};
160
161                 if (mailtoComponents.subject) headers["subject"] = mailtoComponents.subject;
162                 if (mailtoComponents.body) headers["body"] = mailtoComponents.body;
163
164                 const fields = [];
165                 for (const name in headers) {
166                         if (headers[name] !== O[name]) {
167                                 fields.push(
168                                         name.replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, toUpperCase).replace(NOT_HFNAME, pctEncChar) +
169                                         "=" +
170                                         headers[name].replace(PCT_ENCODED, decodeUnreserved).replace(PCT_ENCODED, toUpperCase).replace(NOT_HFVALUE, pctEncChar)
171                                 );
172                         }
173                 }
174                 if (fields.length) {
175                         components.query = fields.join("&");
176                 }
177
178                 return components;
179         }
180 }
181
182 export default handler;