openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
548 lines (547 loc) • 25.4 kB
JavaScript
import { r as __exportAll } from "./rolldown-runtime-Dr7-SnC6.mjs";
//#region node_modules/.pnpm/uc.micro@3.0.0/node_modules/uc.micro/build/index.mjs
var build_exports = /* @__PURE__ */ __exportAll({
Any: () => Any,
Cc: () => Cc,
Cf: () => Cf,
P: () => P,
S: () => S,
Z: () => Z
});
const Any = /[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/;
const Cc = /[\0-\x1F\x7F-\x9F]/;
const Cf = /[\xAD\u0600-\u0605\u061C\u06DD\u070F\u0890\u0891\u08E2\u180E\u200B-\u200F\u202A-\u202E\u2060-\u2064\u2066-\u206F\uFEFF\uFFF9-\uFFFB]|\uD804[\uDCBD\uDCCD]|\uD80D[\uDC30-\uDC3F]|\uD82F[\uDCA0-\uDCA3]|\uD834[\uDD73-\uDD7A]|\uDB40[\uDC01\uDC20-\uDC7F]/;
const P = /[!-#%-\*,-\/:;\?@\[-\]_\{\}\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061D-\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C77\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B4E\u1B4F\u1B5A-\u1B60\u1B7D-\u1B7F\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4F\u2E52-\u2E5D\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD803[\uDD6E\uDEAD\uDED0\uDF55-\uDF59\uDF86-\uDF89]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9\uDFD4\uDFD5\uDFD7\uDFD8]|\uD805[\uDC4B-\uDC4F\uDC5A\uDC5B\uDC5D\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDE60-\uDE6C\uDEB9\uDF3C-\uDF3E]|\uD806[\uDC3B\uDD44-\uDD46\uDDE2\uDE3F-\uDE46\uDE9A-\uDE9C\uDE9E-\uDEA2\uDF00-\uDF09\uDFE1]|\uD807[\uDC41-\uDC45\uDC70\uDC71\uDEF7\uDEF8\uDF43-\uDF4F\uDFFF]|\uD809[\uDC70-\uDC74]|\uD80B[\uDFF1\uDFF2]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD81B[\uDD6D-\uDD6F\uDE97-\uDE9A\uDFE2]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]|\uD839\uDDFF|\uD83A[\uDD5E\uDD5F]/;
const S = /[\$\+<->\^`\|~\xA2-\xA6\xA8\xA9\xAC\xAE-\xB1\xB4\xB8\xD7\xF7\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u02FF\u0375\u0384\u0385\u03F6\u0482\u058D-\u058F\u0606-\u0608\u060B\u060E\u060F\u06DE\u06E9\u06FD\u06FE\u07F6\u07FE\u07FF\u0888\u09F2\u09F3\u09FA\u09FB\u0AF1\u0B70\u0BF3-\u0BFA\u0C7F\u0D4F\u0D79\u0E3F\u0F01-\u0F03\u0F13\u0F15-\u0F17\u0F1A-\u0F1F\u0F34\u0F36\u0F38\u0FBE-\u0FC5\u0FC7-\u0FCC\u0FCE\u0FCF\u0FD5-\u0FD8\u109E\u109F\u1390-\u1399\u166D\u17DB\u1940\u19DE-\u19FF\u1B61-\u1B6A\u1B74-\u1B7C\u1FBD\u1FBF-\u1FC1\u1FCD-\u1FCF\u1FDD-\u1FDF\u1FED-\u1FEF\u1FFD\u1FFE\u2044\u2052\u207A-\u207C\u208A-\u208C\u20A0-\u20C1\u2100\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u2140-\u2144\u214A-\u214D\u214F\u218A\u218B\u2190-\u2307\u230C-\u2328\u232B-\u2429\u2440-\u244A\u249C-\u24E9\u2500-\u2767\u2794-\u27C4\u27C7-\u27E5\u27F0-\u2982\u2999-\u29D7\u29DC-\u29FB\u29FE-\u2B73\u2B76-\u2BFF\u2CE5-\u2CEA\u2E50\u2E51\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFF\u3004\u3012\u3013\u3020\u3036\u3037\u303E\u303F\u309B\u309C\u3190\u3191\u3196-\u319F\u31C0-\u31E5\u31EF\u3200-\u321E\u322A-\u3247\u3250\u3260-\u327F\u328A-\u32B0\u32C0-\u33FF\u4DC0-\u4DFF\uA490-\uA4C6\uA700-\uA716\uA720\uA721\uA789\uA78A\uA828-\uA82B\uA836-\uA839\uAA77-\uAA79\uAB5B\uAB6A\uAB6B\uFB29\uFBB2-\uFBD2\uFD40-\uFD4F\uFD90\uFD91\uFDC8-\uFDCF\uFDFC-\uFDFF\uFE62\uFE64-\uFE66\uFE69\uFF04\uFF0B\uFF1C-\uFF1E\uFF3E\uFF40\uFF5C\uFF5E\uFFE0-\uFFE6\uFFE8-\uFFEE\uFFFC\uFFFD]|\uD800[\uDD37-\uDD3F\uDD79-\uDD89\uDD8C-\uDD8E\uDD90-\uDD9C\uDDA0\uDDD0-\uDDFC]|\uD802[\uDC77\uDC78\uDEC8]|\uD803[\uDD8E\uDD8F\uDED1-\uDED8]|\uD805\uDF3F|\uD807[\uDFD5-\uDFF1]|\uD81A[\uDF3C-\uDF3F\uDF45]|\uD82F\uDC9C|\uD833[\uDC00-\uDCEF\uDCFA-\uDCFC\uDD00-\uDEB3\uDEBA-\uDED0\uDEE0-\uDEF0\uDF50-\uDFC3]|\uD834[\uDC00-\uDCF5\uDD00-\uDD26\uDD29-\uDD64\uDD6A-\uDD6C\uDD83\uDD84\uDD8C-\uDDA9\uDDAE-\uDDEA\uDE00-\uDE41\uDE45\uDF00-\uDF56]|\uD835[\uDEC1\uDEDB\uDEFB\uDF15\uDF35\uDF4F\uDF6F\uDF89\uDFA9\uDFC3]|\uD836[\uDC00-\uDDFF\uDE37-\uDE3A\uDE6D-\uDE74\uDE76-\uDE83\uDE85\uDE86]|\uD838[\uDD4F\uDEFF]|\uD83B[\uDCAC\uDCB0\uDD2E\uDEF0\uDEF1]|\uD83C[\uDC00-\uDC2B\uDC30-\uDC93\uDCA0-\uDCAE\uDCB1-\uDCBF\uDCC1-\uDCCF\uDCD1-\uDCF5\uDD0D-\uDDAD\uDDE6-\uDE02\uDE10-\uDE3B\uDE40-\uDE48\uDE50\uDE51\uDE60-\uDE65\uDF00-\uDFFF]|\uD83D[\uDC00-\uDED8\uDEDC-\uDEEC\uDEF0-\uDEFC\uDF00-\uDFD9\uDFE0-\uDFEB\uDFF0]|\uD83E[\uDC00-\uDC0B\uDC10-\uDC47\uDC50-\uDC59\uDC60-\uDC87\uDC90-\uDCAD\uDCB0-\uDCBB\uDCC0\uDCC1\uDCD0-\uDCD8\uDD00-\uDE57\uDE60-\uDE6D\uDE70-\uDE7C\uDE80-\uDE8A\uDE8E-\uDEC6\uDEC8\uDECD-\uDEDC\uDEDF-\uDEEA\uDEEF-\uDEF8\uDF00-\uDF92\uDF94-\uDFEF\uDFFA]/;
const Z = /[ \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]/;
//#endregion
//#region node_modules/.pnpm/linkify-it@6.1.0/node_modules/linkify-it/build/index.mjs
var REBuilder = class {
src_Any = Any.source;
src_Cc = Cc.source;
src_Z = Z.source;
src_P = P.source;
src_ZPCc = [
this.src_Z,
this.src_P,
this.src_Cc
].join("|");
src_ZCc = [this.src_Z, this.src_Cc].join("|");
cache = {};
opts = {
maxLength: 1e4,
urlAuth: false,
schema_names: []
};
constructor(opts = {}) {
this.opts = {
...this.opts,
...opts
};
}
set(opts = {}) {
this.opts = {
...this.opts,
...opts
};
this.cache = {};
return this;
}
escapeRE(str) {
return str.replace(/[.?*+^$[\]\\(){}|-]/g, "\\$&");
}
nestedPairRE(open, close, depth = 4) {
const openRE = this.escapeRE(open);
const closeRE = this.escapeRE(close);
const atom = `(?:(?!${this.src_ZCc}|${openRE}|${closeRE}).)`;
let pair = `${openRE}${atom}{0,1000}${closeRE}`;
for (let level = 2; level <= depth; level++) pair = `${openRE}(?:${atom}|${pair}){0,1000}${closeRE}`;
return pair;
}
get_text_separators() {
return this.cache.text_separators ??= /[><\uff5c]/;
}
get_pseudo_letter() {
return this.cache.src_pseudo_letter ??= new RegExp(`(?:(?!${this.get_text_separators().source}|${this.src_ZPCc})${this.src_Any})`);
}
get_ipv4_addr() {
return this.cache.src_ip4 ??= /* @__PURE__ */ new RegExp("(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])[.]){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])");
}
get_ipv6_addr() {
const h16 = "[0-9A-Fa-f]{1,4}";
const ls32 = `(?:(?:${h16}:${h16})|${this.get_ipv4_addr().source})`;
return this.cache.src_ip6_addr ??= new RegExp(`(?:(?:${h16}:){6}${ls32}|::(?:${h16}:){5}${ls32}|(?:${h16})?::(?:${h16}:){4}${ls32}|(?:(?:${h16}:){0,1}${h16})?::(?:${h16}:){3}${ls32}|(?:(?:${h16}:){0,2}${h16})?::(?:${h16}:){2}${ls32}|(?:(?:${h16}:){0,3}${h16})?::${h16}:${ls32}|(?:(?:${h16}:){0,4}${h16})?::${ls32}|(?:(?:${h16}:){0,5}${h16})?::${h16}|(?:(?:${h16}:){0,6}${h16})?::)`);
}
get_ipv6_url_host() {
return this.cache.src_ip6_host ??= new RegExp(`\\[${this.get_ipv6_addr().source}\\]`);
}
get_ipv6_mail_host() {
return this.cache.src_ipv6_mail_host ??= new RegExp(`\\[IPv6:${this.get_ipv6_addr().source}\\]`);
}
get_auth() {
return this.cache.src_auth ??= new RegExp(`(?:(?:(?!${this.src_ZCc}|[@/\\[\\]()]).){1,50}@)?`);
}
get_port() {
return this.cache.src_port ??= /* @__PURE__ */ new RegExp("(?::(?:6(?:[0-4]\\d{3}|5(?:[0-4]\\d{2}|5(?:[0-2]\\d|3[0-5])))|[1-5]?\\d{1,4}))?");
}
get_host_terminator() {
return this.cache.src_host_terminator ??= new RegExp(`(?=$|${this.get_text_separators().source}|${this.src_ZPCc})(?!${this.opts["---"] ? "-(?!--)|" : "-|"}_|:\\d|\\.-|\\.(?!$|${this.src_ZPCc}))`);
}
get_path_terminator() {
return this.cache.src_path_terminator ??= new RegExp(`${this.src_ZPCc}|${this.get_text_separators().source}`);
}
get_path() {
return this.cache.src_path ??= new RegExp(`(?:[/?#](?:${this.nestedPairRE("[", "]")}|${this.nestedPairRE("(", ")")}|${this.nestedPairRE("{", "}")}|\\"(?:(?!${this.src_ZCc}|["]).){1,100}\\"|\\'(?:(?!${this.src_ZCc}|[']).){1,100}\\'|\\'(?=${this.get_pseudo_letter().source}|[-])|\\.{2,20}[:]?[a-zA-Z0-9%/&]|\\.(?!${this.src_ZCc}|[.]|$)|` + (this.opts["---"] ? "\\-(?!--(?:[^-]|$))(?:-{0,19})|" : "\\-{1,20}|") + `,(?!${this.src_ZCc}|$)|;(?!${this.src_ZCc}|$)|\\!{1,20}(?!${this.src_ZCc}|[!]|$)|\\?(?!${this.src_ZCc}|[?]|$)|` + this.get_path_extra().source + `[\\\\/:%@#&=_~*]|(?!${this.get_path_terminator().source}).){1,${this.opts.maxLength}}|\\/)?`);
}
get_mail_name() {
return this.cache.src_mail_name ??= /* @__PURE__ */ new RegExp("[-!#$%&'*+/=?^_`{|}~a-zA-Z0-9](?:[-!#$%&'*+/=?^_`{|}~a-zA-Z0-9]|[.](?=[-!#$%&'*+/=?^_`{|}~a-zA-Z0-9])){0,63}");
}
get_xn() {
return this.cache.src_xn ??= /* @__PURE__ */ new RegExp("xn--[a-z0-9\\-]{1,59}");
}
get_tld() {
if (this.cache.tld) return this.cache.tld;
const tlds_src = [...new Set(this.opts.tlds || [])].sort().reverse().join("|");
this.cache.tld = new RegExp(`${tlds_src || "$#none#$"}|${this.get_xn().source}`);
return this.cache.tld;
}
get_domain_root() {
return this.cache.src_domain_root ??= new RegExp("(?:" + this.get_xn().source + `|${this.get_pseudo_letter().source}{1,63})`);
}
get_domain() {
return this.cache.src_domain ??= new RegExp("(?:" + this.get_xn().source + `|(?:${this.get_pseudo_letter().source})|(?:${this.get_pseudo_letter().source}(?:-|${this.get_pseudo_letter().source}){0,61}${this.get_pseudo_letter().source}))`);
}
get_url_host_port() {
return this.cache.url_host_port ??= new RegExp("(?:" + this.get_ipv6_url_host().source + `|(?:(?:(?:${this.get_domain().source})\\.){0,10}${this.get_domain().source}))` + this.get_port().source + this.get_host_terminator().source);
}
get_fuzzy_url_host_port() {
return this.cache.fuzzy_url_host_port ??= new RegExp("(?:" + (this.opts.fuzzyIP ? this.get_ipv4_addr().source + "|" : "") + `(?:(?:(?:${this.get_domain().source})\\.){1,10}(?:${this.get_tld().source})))` + this.get_host_terminator().source);
}
get_mail_host() {
return this.cache.src_mail_host ??= new RegExp("(?:" + this.get_ipv6_mail_host().source + `|(?:(?:(?:${this.get_domain().source})\\.){0,4}${this.get_domain().source}))` + this.get_host_terminator().source);
}
get_fuzzy_mail_host() {
return this.cache.src_fuzzy_mail_host ??= new RegExp("(?:" + this.get_ipv6_mail_host().source + `|(?:(?:(?:${this.get_domain().source})[.]){1,4}${this.get_domain_root().source}))` + this.get_host_terminator().source);
}
get_path_extra() {
return this.cache.src_path_extra ??= /* @__PURE__ */ new RegExp("");
}
get_fuzzy_mail_host_search() {
return this.cache.mail_fuzzy_host_search ??= new RegExp(`@${this.get_fuzzy_mail_host().source}`, "ig");
}
get_fuzzy_link_search() {
return this.cache.link_fuzzy_search ??= new RegExp(`(^|(?![.:/\\-_@])(?:[$+<=>^\`|\uff5c]|${this.src_ZPCc}))(?:(?![$+<=>^\`|\uff5c])${this.get_fuzzy_url_host_port().source}${this.get_path().source})`, "ig");
}
get_http_validator() {
return this.cache.http_validator ??= new RegExp("\\/\\/" + (this.opts.urlAuth ? this.get_auth().source : "") + this.get_url_host_port().source + this.get_path().source, "iy");
}
get_relative_proto_validator() {
return this.cache.relative_proto_validator ??= new RegExp((this.opts.urlAuth ? this.get_auth().source : "") + `(?:localhost|${this.get_ipv6_url_host().source}|(?:(?:${this.get_domain().source})[.]){1,10}${this.get_domain_root().source})` + this.get_port().source + this.get_host_terminator().source + this.get_path().source, "iy");
}
get_mail_name_validator() {
return this.cache.mail_name_validator ??= new RegExp(`(?:^|${this.get_text_separators().source}|"|\\(|${this.src_ZCc})(${this.get_mail_name().source})$`);
}
get_mailto_validator() {
return this.cache.mailto_validator ??= new RegExp(`${this.get_mail_name().source}@${this.get_mail_host().source}`, "iy");
}
get_schema_names() {
return this.cache.schema_names ??= new RegExp((this.opts.schema_names || []).map((name) => this.escapeRE(name)).join("|"));
}
get_schema_search() {
return this.cache.schema_search ??= new RegExp(`(^|(?!_)(?:[><\uff5c]|${this.src_ZPCc}))(${this.get_schema_names().source})`, "ig");
}
get_schema_at_start() {
return this.cache.schema_at_start ??= new RegExp(`^${this.get_schema_search().source}`, "i");
}
};
var web_schema = {
validate: (text, pos, self) => {
const re = self.re.get_http_validator();
re.lastIndex = pos;
const m = re.exec(text);
return m ? m[0].length : 0;
},
normalize: (match, self) => self.normalize(match)
};
var defaultSchemas = {
"http:": web_schema,
"https:": web_schema,
"ftp:": web_schema,
"//": {
validate: function(text, pos, self) {
const re = self.re.get_relative_proto_validator();
re.lastIndex = pos;
const m = re.exec(text);
if (m) {
if (pos >= 3 && text[pos - 3] === ":") return 0;
if (pos >= 3 && text[pos - 3] === "/") return 0;
return m[0].length;
}
return 0;
},
normalize: (match, self) => self.normalize(match)
},
"mailto:": {
validate: function(text, pos, self) {
const re = self.re.get_mailto_validator();
re.lastIndex = pos;
const m = re.exec(text);
return m ? m[0].length : 0;
},
normalize: (match, self) => self.normalize(match)
}
};
var tlds_2ch = "a:cdefgilmnoqrstuwxz|b:abdefghijmnorstvwyz|c:acdfghiklmnoruvwxyz|d:ejkmoz|e:cegrstu|f:ijkmor|g:abdefghilmnpqrstuwy|h:kmnrtu|i:delmnoqrst|j:emop|k:eghimnprwyz|l:abcikrstuvy|m:acdeghklmnopqrstuvwxyz|n:acefgilopruz|o:m|p:aefghklmnrstwy|q:a|r:eosuw|s:abcdeghijklmnortuvxyz|t:cdfghjklmnortvwz|u:agksyz|v:aceginu|w:fs|y:et|z:amw";
var tlds_default = "biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф";
function unpackTlds() {
const result = tlds_default.split("|");
tlds_2ch.split("|").forEach((item) => {
const sep = item.indexOf(":");
const prefix = item.slice(0, sep);
for (const suffix of item.slice(sep + 1)) result.push(prefix + suffix);
});
return result;
}
var defaultOptions = {
fuzzyLink: false,
fuzzyEmail: true,
fuzzyIP: false,
"---": false,
tlds: unpackTlds(),
urlAuth: false,
maxLength: 1e4
};
/**
* Match result returned by {@link LinkifyIt.match} and
* {@link LinkifyIt.matchAtStart}.
*
* @category types
*/
var Match = class {
/** Prefix (protocol) for matched string. Empty for fuzzy links. */
schema;
/** First position of matched string. */
index;
/** Next position after matched string. */
lastIndex;
/** Matched string. */
raw;
/** Normalized text of matched string. */
text;
/** Normalized URL of matched string. */
url;
constructor(text, schema, index, lastIndex) {
const raw = text.slice(index, lastIndex);
this.schema = schema.toLowerCase();
this.index = index;
this.lastIndex = lastIndex;
this.raw = raw;
this.text = raw;
this.url = raw;
}
};
/** Linkifier instance. */
var LinkifyIt = class {
__opts__;
__schemas__;
re;
/**
* Creates new linkifier instance.
*
* By default understands:
*
* - `http(s)://...` , `ftp://...`, `mailto:...` & `//...` links
* - "fuzzy" emails (foo@bar.com).
*
* See {@link LinkifyConstructorOptions} for available options.
*
* @param options Recognition options.
*
* @example
* ```javascript
* import { LinkifyIt } from 'linkify-it'
*
* const linkify = new LinkifyIt({ fuzzyLink: true })
*
* linkify
* .tlds(require('tlds')) // Reload with full TLD list
* .tlds('onion', true) // Add unofficial `.onion` domain
* .add('ftp:', null) // Disable `ftp:` protocol
* .set({ fuzzyIP: true }) // Enable IPs in fuzzy links
*
* console.log(linkify.test('Site github.com!')) // true
* console.log(linkify.match('Site github.com!'))
* ```
*/
constructor(options = {}) {
const { rebuilder, ...linkifyOptions } = options;
this.__opts__ = {
...defaultOptions,
...linkifyOptions
};
this.__schemas__ = { ...defaultSchemas };
this.re = rebuilder || new REBuilder();
this.re.set({
...this.__opts__,
schema_names: Object.keys(this.__schemas__)
});
}
/**
* Add new rule definition.
*
* `schema` is a link prefix (usually, protocol name with `:` at the end,
* `skype:` for example). `linkify-it` makes sure that prefix is not
* preceded with alphanumeric char and symbols. Only whitespaces and
* punctuation allowed.
*
* `definition` is a rule to check tail after link prefix. To disable an
* existing rule, pass `null`.
*
* @param schema Rule name (fixed pattern prefix).
* @param definition Schema definition, or `null` to disable the rule.
*
* See [twitter mentions example](https://github.com/markdown-it/linkify-it/blob/master/examples/twitter.mjs).
*/
add(schema, definition = null) {
if (!definition) delete this.__schemas__[schema];
else {
const def = {
normalize: (match, self) => self.normalize(match),
...definition
};
this.__schemas__[schema] = def;
}
this.re.set({
...this.__opts__,
schema_names: Object.keys(this.__schemas__)
});
return this;
}
/**
* Set recognition options for links without schema.
*
* @param options Recognition options.
*/
set(options = {}) {
this.__opts__ = {
...this.__opts__,
...options
};
this.re.set({
...this.__opts__,
schema_names: Object.keys(this.__schemas__)
});
return this;
}
/**
* Searches linkifiable pattern and returns `true` on success or `false` on fail.
*
* @param text Text to scan.
*/
test(text) {
if (!text.length) return false;
let m, re;
re = this.re.get_schema_search();
re.lastIndex = 0;
while ((m = re.exec(text)) !== null) if (this.testSchemaAt(text, m[2], re.lastIndex)) return true;
if (this.__opts__.fuzzyLink && this.__schemas__["http:"]) {
re = this.re.get_fuzzy_link_search();
re.lastIndex = 0;
if (re.exec(text) !== null) return true;
}
if (this.__opts__.fuzzyEmail && this.__schemas__["mailto:"]) {
if (text.indexOf("@") >= 0) {
const mailHostRe = this.re.get_fuzzy_mail_host_search();
const mailNameRe = this.re.get_mail_name_validator();
mailHostRe.lastIndex = 0;
while ((m = mailHostRe.exec(text)) !== null) {
const name = text.slice(Math.max(0, m.index - 65), m.index);
if (mailNameRe.test(name)) return true;
}
}
}
return false;
}
/**
* Similar to {@link LinkifyIt.test} but checks only specific protocol tail exactly
* at given position. Returns length of found pattern (0 on fail).
*
* @param text Text to scan.
* @param schema Rule (schema) name.
* @param pos Text offset to check from.
*/
testSchemaAt(text, schema, pos) {
if (!this.__schemas__[schema.toLowerCase()]) return 0;
return this.__schemas__[schema.toLowerCase()].validate(text.slice(0, pos + this.__opts__.maxLength), pos, this);
}
/**
* Returns array of found link descriptions or `null` on fail. We strongly
* recommend to use {@link LinkifyIt.test} first, for best speed.
*
* @param text Text to scan.
*/
match(text) {
const result = [];
const schemaRe = this.re.get_schema_search();
let fuzzyLinkRe;
let mailHostRe;
let mailNameRe;
let fuzzyLinkCandidate;
let fuzzyEmailCandidate;
let schemaPrefix;
let schemaDone = false;
let fuzzyLinkDone = false;
let fuzzyEmailDone = false;
let pos = 0;
if (!text.length) return null;
schemaRe.lastIndex = 0;
if (this.__opts__.fuzzyLink && this.__schemas__["http:"]) {
fuzzyLinkRe = this.re.get_fuzzy_link_search();
fuzzyLinkRe.lastIndex = 0;
}
if (this.__opts__.fuzzyEmail && this.__schemas__["mailto:"]) {
mailHostRe = this.re.get_fuzzy_mail_host_search();
mailHostRe.lastIndex = 0;
mailNameRe = this.re.get_mail_name_validator();
}
for (;;) {
const scanFrom = Math.max(pos - 1, 0);
if (mailHostRe && mailNameRe && !fuzzyEmailDone && (!fuzzyEmailCandidate || fuzzyEmailCandidate.index < pos)) {
if (mailHostRe.lastIndex < scanFrom) mailHostRe.lastIndex = scanFrom;
for (;;) {
const m = mailHostRe.exec(text);
if (!m) {
fuzzyEmailDone = true;
fuzzyEmailCandidate = void 0;
break;
}
const name = mailNameRe.exec(text.slice(Math.max(0, m.index - 65), m.index));
if (!name) continue;
fuzzyEmailCandidate = {
schema: "mailto:",
index: m.index - name[1].length,
lastIndex: m.index + m[0].length
};
if (fuzzyEmailCandidate.index >= pos) break;
if (mailHostRe.lastIndex < scanFrom) mailHostRe.lastIndex = scanFrom;
}
}
if (fuzzyLinkRe && !fuzzyLinkDone && (!fuzzyLinkCandidate || fuzzyLinkCandidate.index < pos)) {
if (fuzzyLinkRe.lastIndex < scanFrom) fuzzyLinkRe.lastIndex = scanFrom;
for (;;) {
const m = fuzzyLinkRe.exec(text);
if (!m) {
fuzzyLinkDone = true;
fuzzyLinkCandidate = void 0;
break;
}
fuzzyLinkCandidate = {
schema: "",
index: m.index + m[1].length,
lastIndex: m.index + m[0].length
};
if (fuzzyLinkCandidate.index >= pos) break;
if (fuzzyLinkRe.lastIndex < scanFrom) fuzzyLinkRe.lastIndex = scanFrom;
}
}
let fuzzyCandidate = fuzzyEmailCandidate;
if (!fuzzyCandidate || fuzzyLinkCandidate && (fuzzyLinkCandidate.index < fuzzyCandidate.index || fuzzyLinkCandidate.index === fuzzyCandidate.index && fuzzyLinkCandidate.lastIndex > fuzzyCandidate.lastIndex)) fuzzyCandidate = fuzzyLinkCandidate;
let schemaCandidate;
if (!schemaDone) for (;;) {
if (!schemaPrefix) {
if (schemaRe.lastIndex < scanFrom) schemaRe.lastIndex = scanFrom;
const m = schemaRe.exec(text);
if (!m) {
schemaDone = true;
break;
}
schemaPrefix = {
schema: m[2],
index: m.index + m[1].length,
lastIndex: m.index + m[0].length
};
}
if (schemaPrefix.index < pos) {
schemaPrefix = void 0;
continue;
}
if (fuzzyCandidate && schemaPrefix.index > fuzzyCandidate.index) break;
const prefix = schemaPrefix;
schemaPrefix = void 0;
const len = this.testSchemaAt(text, prefix.schema, prefix.lastIndex);
if (len) {
schemaCandidate = {
schema: prefix.schema,
index: prefix.index,
lastIndex: prefix.lastIndex + len
};
break;
}
}
let candidate = schemaCandidate;
if (!candidate || fuzzyEmailCandidate && (fuzzyEmailCandidate.index < candidate.index || fuzzyEmailCandidate.index === candidate.index && fuzzyEmailCandidate.lastIndex > candidate.lastIndex)) candidate = fuzzyEmailCandidate;
if (!candidate || fuzzyLinkCandidate && (fuzzyLinkCandidate.index < candidate.index || fuzzyLinkCandidate.index === candidate.index && fuzzyLinkCandidate.lastIndex > candidate.lastIndex)) candidate = fuzzyLinkCandidate;
if (!candidate) break;
if (candidate === fuzzyEmailCandidate) fuzzyEmailCandidate = void 0;
else if (candidate === fuzzyLinkCandidate) fuzzyLinkCandidate = void 0;
const match = new Match(text, candidate.schema, candidate.index, candidate.lastIndex);
if (match.schema) this.__schemas__[match.schema].normalize(match, this);
else this.normalize(match);
result.push(match);
pos = candidate.lastIndex;
}
if (result.length) return result;
return null;
}
/**
* Returns fully-formed (not fuzzy) link if it starts at the beginning
* of the string, and null otherwise.
*
* @param text Text to scan.
*/
matchAtStart(text) {
if (!text.length) return null;
const m = this.re.get_schema_at_start().exec(text);
if (!m) return null;
const len = this.testSchemaAt(text, m[2], m[0].length);
if (!len) return null;
const match = new Match(text, m[2], m.index + m[1].length, m.index + m[0].length + len);
this.__schemas__[match.schema].normalize(match, this);
return match;
}
/**
* Load (or merge) new TLDs list. Those are used for fuzzy links (without
* prefix) to avoid false positives. By default this algorithm is used:
*
* - hostname with any 2-letter root zones are ok.
* - biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф
* are ok.
* - encoded (`xn--...`) root zones are ok.
*
* If list is replaced, then exact match for 2-chars root zones will be checked.
*
* @param list List of TLDs.
* @param keepOld Merge with current list if `true` (`false` by default).
*/
tlds(list, keepOld = false) {
list = Array.isArray(list) ? list : [list];
if (!keepOld) this.__opts__.tlds = list;
else this.__opts__.tlds = this.__opts__.tlds.concat(list);
this.re.set({
...this.__opts__,
schema_names: Object.keys(this.__schemas__)
});
return this;
}
/**
* Default normalizer (if schema does not define its own).
*
* @param match Match to normalize.
*/
normalize(match) {
if (!match.schema) match.url = `http://${match.url}`;
if (match.schema === "mailto:" && !/^mailto:/i.test(match.url)) match.url = `mailto:${match.url}`;
}
};
//#endregion
export { build_exports as i, P as n, S as r, LinkifyIt as t };