linkify-it
Advanced tools
| {"version":3,"file":"index.cjs.js","names":[],"sources":["../src/rebuilder.ts","../src/linkifyit.ts"],"sourcesContent":["/* eslint-disable no-return-assign, prefer-regex-literals */\n\nimport { Any, Cc, Z, P } from 'uc.micro'\n\n/**\n * @category types\n */\nexport interface REBuilderOptions {\n '---'?: boolean\n fuzzyIP?: boolean\n schema_names?: string[]\n tlds?: string[]\n urlAuth?: boolean\n maxLength?: number\n}\n\nexport class REBuilder {\n src_Any = Any.source\n src_Cc = Cc.source\n src_Z = Z.source\n src_P = P.source\n // \\p{\\Z\\P\\Cc\\CF} (white spaces + control + format + punctuation)\n src_ZPCc = [this.src_Z, this.src_P, this.src_Cc].join('|')\n // \\p{\\Z\\Cc} (white spaces + control)\n src_ZCc = [this.src_Z, this.src_Cc].join('|')\n cache: Record<string, RegExp | undefined> = {}\n opts: REBuilderOptions = { maxLength: 10000, urlAuth: false, schema_names: [] }\n\n constructor (opts: REBuilderOptions = {}) {\n this.opts = { ...this.opts, ...opts }\n }\n\n set (opts: REBuilderOptions = {}) {\n this.opts = { ...this.opts, ...opts }\n\n this.cache = {}\n return this\n }\n\n escapeRE (str: string) { return str.replace(/[.?*+^$[\\]\\\\(){}|-]/g, '\\\\$&') }\n\n nestedPairRE (open: string, close: string, depth = 4) {\n const openRE = this.escapeRE(open)\n const closeRE = this.escapeRE(close)\n const atom = `(?:(?!${this.src_ZCc}|${openRE}|${closeRE}).)`\n\n let pair = `${openRE}${atom}{0,1000}${closeRE}`\n\n for (let level = 2; level <= depth; level++) {\n pair = `${openRE}(?:${atom}|${pair}){0,1000}${closeRE}`\n }\n\n return pair\n }\n\n // Partials\n\n get_text_separators () {\n // Experimental. List of chars, completely prohibited in links\n // because can separate it from other part of text\n return this.cache.text_separators ??= /[><\\uff5c]/\n }\n\n get_pseudo_letter () {\n return this.cache.src_pseudo_letter ??= new RegExp(\n // All possible word characters (everything without punctuation, spaces & controls)\n // Defined via punctuation & spaces to save space\n // Should be something like \\p{\\L\\N\\S\\M} (\\w but without `_`)\n `(?:(?!${this.get_text_separators().source}|${this.src_ZPCc})${this.src_Any})`\n )\n }\n\n get_ipv4_addr () {\n return this.cache.src_ip4 ??= new RegExp(\n '(?:' +\n '(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])[.]' +\n '){3}' +\n '(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])'\n )\n }\n\n get_ipv6_addr () {\n const h16 = '[0-9A-Fa-f]{1,4}'\n const ls32 = `(?:(?:${h16}:${h16})|${this.get_ipv4_addr().source})`\n\n return this.cache.src_ip6_addr ??= new RegExp(\n '(?:' +\n `(?:${h16}:){6}${ls32}|` +\n `::(?:${h16}:){5}${ls32}|` +\n `(?:${h16})?::(?:${h16}:){4}${ls32}|` +\n `(?:(?:${h16}:){0,1}${h16})?::(?:${h16}:){3}${ls32}|` +\n `(?:(?:${h16}:){0,2}${h16})?::(?:${h16}:){2}${ls32}|` +\n `(?:(?:${h16}:){0,3}${h16})?::${h16}:${ls32}|` +\n `(?:(?:${h16}:){0,4}${h16})?::${ls32}|` +\n `(?:(?:${h16}:){0,5}${h16})?::${h16}|` +\n `(?:(?:${h16}:){0,6}${h16})?::` +\n ')'\n )\n }\n\n get_ipv6_url_host () {\n return this.cache.src_ip6_host ??= new RegExp(\n `\\\\[${this.get_ipv6_addr().source}\\\\]`\n )\n }\n\n get_ipv6_mail_host () {\n return this.cache.src_ipv6_mail_host ??= new RegExp(\n `\\\\[IPv6:${this.get_ipv6_addr().source}\\\\]`\n )\n }\n\n get_auth () {\n return this.cache.src_auth ??= new RegExp(\n // Prohibit any of \"@/[]()\" in user/pass to avoid wrong domain fetch.\n // Length is capped to exclude possible rescans till the end and avoid O(n^2)\n // DoS. No standard limit, just take something reasonable.\n `(?:(?:(?!${this.src_ZCc}|[@/\\\\[\\\\]()]).){1,50}@)?`\n )\n }\n\n get_port () {\n return this.cache.src_port ??= new RegExp(\n '(?::(?:6(?:[0-4]\\\\d{3}|5(?:[0-4]\\\\d{2}|5(?:[0-2]\\\\d|3[0-5])))|[1-5]?\\\\d{1,4}))?'\n )\n }\n\n get_host_terminator () {\n // Force greedy fetch, we should not stop earlier than host part is fully fetched.\n return this.cache.src_host_terminator ??= new RegExp(\n `(?=$|${this.get_text_separators().source}|${this.src_ZPCc})` +\n `(?!${this.opts['---'] ? '-(?!--)|' : '-|'}_|:\\\\d|\\\\.-|\\\\.(?!$|${this.src_ZPCc}))`\n )\n }\n\n get_path_terminator () {\n return this.cache.src_path_terminator ??= new RegExp(\n `${this.src_ZPCc}|${this.get_text_separators().source}`\n // `${this.src_ZCc}|${this.get_text_separators().source}|[()[\\\\]{}.,\"'?!\\\\-;]`\n )\n }\n\n get_path () {\n return this.cache.src_path ??= new RegExp(\n '(?:' +\n '[/?#]' +\n '(?:' +\n `${this.nestedPairRE('[', ']')}|` +\n `${this.nestedPairRE('(', ')')}|` +\n `${this.nestedPairRE('{', '}')}|` +\n `\\\\\"(?:(?!${this.src_ZCc}|[\"]).){1,100}\\\\\"|` +\n `\\\\'(?:(?!${this.src_ZCc}|[']).){1,100}\\\\'|` +\n\n // allow `I'm_king` if no pair found\n `\\\\'(?=${this.get_pseudo_letter().source}|[-])|` +\n\n // 1. google has many dots in \"google search\" links (#66, #81).\n // github has ... in commit range links,\n // Restrict to\n // - english\n // - percent-encoded\n // - parts of file path\n // - params separator\n // until more examples found.\n //\n // 2. Allow `..:XX` for Odysee links (optional `:`), #100\n // This may be narrowed down later via separate rule.\n '\\\\.{2,20}[:]?[a-zA-Z0-9%/&]|' +\n\n `\\\\.(?!${this.src_ZCc}|[.]|$)|` +\n (this.opts['---']\n ? '\\\\-(?!--(?:[^-]|$))(?:-{0,19})|' // `---` => long dash, terminate\n : '\\\\-{1,20}|'\n ) +\n // allow `,,,` in paths\n `,(?!${this.src_ZCc}|$)|` +\n\n // allow `;` if not followed by space-like char\n `;(?!${this.src_ZCc}|$)|` +\n\n // allow `!!!` in paths, but not at the end\n `\\\\!{1,20}(?!${this.src_ZCc}|[!]|$)|` +\n\n `\\\\?(?!${this.src_ZCc}|[?]|$)|` +\n\n this.get_path_extra().source +\n\n // allowed punctuation chars in path.\n '[\\\\\\\\/:%@#&=_~*]|' +\n\n // if no special rules matched, consume all chars except terminators.\n `(?!${this.get_path_terminator().source}).` +\n `){1,${this.opts.maxLength}}` +\n '|\\\\/' +\n ')?'\n )\n }\n\n get_mail_name () {\n return this.cache.src_mail_name ??= new RegExp(\n // RFC 5321 dot-string only (no quoted-string), max 64 ASCII characters.\n \"[-!#$%&'*+/=?^_`{|}~a-zA-Z0-9](?:[-!#$%&'*+/=?^_`{|}~a-zA-Z0-9]|[.](?=[-!#$%&'*+/=?^_`{|}~a-zA-Z0-9])){0,63}\"\n )\n }\n\n get_xn () {\n return this.cache.src_xn ??= new RegExp(\n 'xn--[a-z0-9\\\\-]{1,59}'\n )\n }\n\n get_tld () {\n if (this.cache.tld) return this.cache.tld\n\n const tlds_src = [...new Set(this.opts.tlds || [])].sort().reverse()\n .join('|')\n\n this.cache.tld = new RegExp(\n `${tlds_src || '$#none#$'}|${this.get_xn().source}`\n )\n return this.cache.tld\n }\n\n get_domain_root () {\n return this.cache.src_domain_root ??= new RegExp(\n // More to read about domain names\n // http://serverfault.com/questions/638260/\n\n // Allow letters & digits (http://test1)\n '(?:' +\n this.get_xn().source +\n '|' +\n `${this.get_pseudo_letter().source}{1,63}` +\n ')'\n )\n }\n\n get_domain () {\n return this.cache.src_domain ??= new RegExp(\n '(?:' +\n this.get_xn().source +\n '|' +\n `(?:${this.get_pseudo_letter().source})` +\n '|' +\n `(?:${this.get_pseudo_letter().source}(?:-|${this.get_pseudo_letter().source}){0,61}${this.get_pseudo_letter().source})` +\n ')'\n )\n }\n\n // Host rules, depending on the type\n\n get_url_host_port () {\n return this.cache.url_host_port ??= new RegExp(\n '(?:' +\n // Don't need IP v4 check, because digits are already allowed\n // in normal domain names\n this.get_ipv6_url_host().source +\n '|' +\n `(?:(?:(?:${this.get_domain().source})\\\\.){0,10}${this.get_domain().source})`/* _root */ +\n ')' +\n this.get_port().source +\n this.get_host_terminator().source\n )\n }\n\n get_fuzzy_url_host_port () {\n // - TLD as anchor\n // - No local domains\n return this.cache.fuzzy_url_host_port ??= new RegExp(\n '(?:' +\n (this.opts.fuzzyIP ? this.get_ipv4_addr().source + '|' : '') +\n `(?:(?:(?:${this.get_domain().source})\\\\.){1,10}(?:${this.get_tld().source}))` +\n ')' +\n // No port in fuzzy links to reduce search\n this.get_host_terminator().source\n )\n }\n\n get_mail_host () {\n // Similar to normal url host, but\n // - with different ipv6 format (and without port).\n // - with reduced max subdomains\n return this.cache.src_mail_host ??= new RegExp(\n '(?:' +\n this.get_ipv6_mail_host().source +\n '|' +\n `(?:(?:(?:${this.get_domain().source})\\\\.){0,4}${this.get_domain().source})` +\n ')' +\n this.get_host_terminator().source\n )\n }\n\n get_fuzzy_mail_host () {\n // Similar to normal mail host, but without local domains.\n return this.cache.src_fuzzy_mail_host ??= new RegExp(\n '(?:' +\n this.get_ipv6_mail_host().source +\n '|' +\n `(?:(?:(?:${this.get_domain().source})[.]){1,4}${this.get_domain_root().source})` +\n ')' +\n this.get_host_terminator().source\n )\n }\n\n // Hooks\n\n get_path_extra () {\n return this.cache.src_path_extra ??= new RegExp('')\n }\n\n // \"Public\" rules\n\n get_fuzzy_mail_host_search () {\n return this.cache.mail_fuzzy_host_search ??= new RegExp(\n `@${this.get_fuzzy_mail_host().source}`,\n 'ig'\n )\n }\n\n get_fuzzy_link_search () {\n return this.cache.link_fuzzy_search ??= new RegExp(\n // Fuzzy link can't be prepended with .:/\\- and non punctuation.\n // but can start with > (markdown blockquote)\n `(^|(?![.:/\\\\-_@])(?:[$+<=>^\\`|\\uff5c]|${this.src_ZPCc}))` +\n `(?:(?![$+<=>^\\`|\\uff5c])${this.get_fuzzy_url_host_port().source}${this.get_path().source})`,\n 'ig'\n )\n }\n\n get_http_validator () {\n return this.cache.http_validator ??= new RegExp(\n '\\\\/\\\\/' +\n (this.opts.urlAuth ? this.get_auth().source : '') +\n this.get_url_host_port().source +\n this.get_path().source,\n 'iy'\n )\n }\n\n get_relative_proto_validator () {\n return this.cache.relative_proto_validator ??= new RegExp(\n (this.opts.urlAuth ? this.get_auth().source : '') +\n // Don't allow single-level domains, because of false positives like '//test'\n // with code comments.\n `(?:localhost|${this.get_ipv6_url_host().source}|(?:(?:${this.get_domain().source})[.]){1,10}${this.get_domain_root().source})` +\n this.get_port().source +\n this.get_host_terminator().source +\n this.get_path().source,\n\n 'iy'\n )\n }\n\n get_mail_name_validator () {\n return this.cache.mail_name_validator ??= new RegExp(\n `(?:^|${this.get_text_separators().source}|\"|\\\\(|${this.src_ZCc})` +\n `(${this.get_mail_name().source})$`\n )\n }\n\n get_mailto_validator () {\n return this.cache.mailto_validator ??= new RegExp(\n `${this.get_mail_name().source}@${this.get_mail_host().source}`,\n 'iy'\n )\n }\n\n get_schema_names () {\n return this.cache.schema_names ??= new RegExp((this.opts.schema_names || []).map(name => this.escapeRE(name)).join('|'))\n }\n\n get_schema_search () {\n return this.cache.schema_search ??= new RegExp(\n `(^|(?!_)(?:[><\\uff5c]|${this.src_ZPCc}))(${this.get_schema_names().source})`,\n 'ig'\n )\n }\n\n get_schema_at_start () {\n return this.cache.schema_at_start ??= new RegExp(\n `^${this.get_schema_search().source}`,\n 'i'\n )\n }\n}\n","import { REBuilder } from './rebuilder.ts'\n\n//\n\n/**\n * Recognition options for schemaless links.\n *\n * @category types\n */\nexport interface LinkifyOptions {\n /** Recognize URLs without `http(s)://` prefix. Default `false`. */\n fuzzyLink?: boolean\n /** Recognize emails without `mailto:` prefix. Default `true`. */\n fuzzyEmail?: boolean\n /**\n * Allow IPs in fuzzy links. Can conflict with some texts, like version\n * numbers. Default `false`.\n */\n fuzzyIP?: boolean\n /**\n * Terminate link with `---` if it is considered a long dash. Default `false`.\n */\n '---'?: boolean\n /** Allowed TLDs list for fuzzy links. Replaces the default list when set. */\n tlds?: string[]\n /** Recognize authentication data in URLs. Default `false`. */\n urlAuth?: boolean\n /** Maximum link length. Default `10000`. */\n maxLength?: number\n}\n\nexport interface LinkifyConstructorOptions extends LinkifyOptions {\n /** Custom regular expression builder. */\n rebuilder?: REBuilder\n}\n\n/**\n * Custom schema definition.\n *\n * @category types\n */\nexport interface SchemaOpts {\n /**\n * Checks text after the schema prefix. Should return matched tail length on\n * success, or `0` on fail.\n */\n validate: (text: string, pos: number, self: LinkifyIt) => number\n /**\n * Optional function to normalize `text` and `url` of matched result, for\n * example for `@twitter` mentions.\n */\n normalize?: (match: Match, self: LinkifyIt) => void\n}\n\ntype Schema = Required<SchemaOpts>\n\ninterface MatchCandidate {\n schema: string\n index: number\n lastIndex: number\n}\n\nconst web_schema: Schema = {\n validate: (text: string, pos: number, self: LinkifyIt) => {\n const re = self.re.get_http_validator()\n re.lastIndex = pos\n\n const m = re.exec(text)\n return m ? m[0].length : 0\n },\n normalize: (match: Match, self: LinkifyIt) => self.normalize(match)\n}\n\nconst defaultSchemas: Record<string, Schema> = {\n 'http:': web_schema,\n 'https:': web_schema,\n 'ftp:': web_schema,\n '//': {\n validate: function (text: string, pos: number, self: LinkifyIt) {\n const re = self.re.get_relative_proto_validator()\n re.lastIndex = pos\n\n const m = re.exec(text)\n if (m) {\n // should not be `://` & `///`, that protects from errors in protocol name\n if (pos >= 3 && text[pos - 3] === ':') { return 0 }\n if (pos >= 3 && text[pos - 3] === '/') { return 0 }\n return m[0].length\n }\n return 0\n },\n normalize: (match: Match, self: LinkifyIt) => self.normalize(match)\n },\n 'mailto:': {\n validate: function (text: string, pos: number, self: LinkifyIt) {\n const re = self.re.get_mailto_validator()\n re.lastIndex = pos\n\n const m = re.exec(text)\n return m ? m[0].length : 0\n },\n normalize: (match: Match, self: LinkifyIt) => self.normalize(match)\n }\n}\n\n// List of 2-character tlds (autogenerated by ./support/tlds_2char_gen.js)\nconst 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'\n\n// DON'T try to make PRs with changes. Extend TLDs with LinkifyIt.tlds() instead\nconst tlds_default = 'biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф'\n\nfunction unpackTlds (): string[] {\n const result = tlds_default.split('|')\n\n tlds_2ch.split('|').forEach((item) => {\n const sep = item.indexOf(':')\n\n const prefix = item.slice(0, sep)\n\n for (const suffix of item.slice(sep + 1)) {\n result.push(prefix + suffix)\n }\n })\n\n return result\n}\n\nconst defaultOptions: Required<LinkifyOptions> = {\n fuzzyLink: false,\n fuzzyEmail: true,\n fuzzyIP: false,\n '---': false,\n tlds: unpackTlds(),\n urlAuth: false,\n maxLength: 10000\n}\n\n/**\n * Match result returned by {@link LinkifyIt.match} and\n * {@link LinkifyIt.matchAtStart}.\n *\n * @category types\n */\nexport class Match {\n /** Prefix (protocol) for matched string. Empty for fuzzy links. */\n schema: string\n /** First position of matched string. */\n index: number\n /** Next position after matched string. */\n lastIndex: number\n /** Matched string. */\n raw: string\n /** Normalized text of matched string. */\n text: string\n /** Normalized URL of matched string. */\n url: string\n\n constructor (text: string, schema: string, index: number, lastIndex: number) {\n const raw = text.slice(index, lastIndex)\n\n this.schema = schema.toLowerCase()\n this.index = index\n this.lastIndex = lastIndex\n this.raw = raw\n this.text = raw\n this.url = raw\n }\n}\n\n/** Linkifier instance. */\nexport class LinkifyIt {\n __opts__: Required<LinkifyOptions>\n private __schemas__: Record<string, Schema>\n re: REBuilder\n\n /**\n * Creates new linkifier instance.\n *\n * By default understands:\n *\n * - `http(s)://...` , `ftp://...`, `mailto:...` & `//...` links\n * - \"fuzzy\" emails (foo@bar.com).\n *\n * See {@link LinkifyConstructorOptions} for available options.\n *\n * @param options Recognition options.\n *\n * @example\n * ```javascript\n * import { LinkifyIt } from 'linkify-it'\n *\n * const linkify = new LinkifyIt({ fuzzyLink: true })\n *\n * linkify\n * .tlds(require('tlds')) // Reload with full TLD list\n * .tlds('onion', true) // Add unofficial `.onion` domain\n * .add('ftp:', null) // Disable `ftp:` protocol\n * .set({ fuzzyIP: true }) // Enable IPs in fuzzy links\n *\n * console.log(linkify.test('Site github.com!')) // true\n * console.log(linkify.match('Site github.com!'))\n * ```\n */\n constructor (options: LinkifyConstructorOptions = {}) {\n const { rebuilder, ...linkifyOptions } = options\n\n this.__opts__ = { ...defaultOptions, ...linkifyOptions }\n\n this.__schemas__ = { ...defaultSchemas }\n\n this.re = rebuilder || new REBuilder()\n this.re.set({\n ...this.__opts__,\n schema_names: Object.keys(this.__schemas__)\n })\n }\n\n /**\n * Add new rule definition.\n *\n * `schema` is a link prefix (usually, protocol name with `:` at the end,\n * `skype:` for example). `linkify-it` makes sure that prefix is not\n * preceded with alphanumeric char and symbols. Only whitespaces and\n * punctuation allowed.\n *\n * `definition` is a rule to check tail after link prefix. To disable an\n * existing rule, pass `null`.\n *\n * @param schema Rule name (fixed pattern prefix).\n * @param definition Schema definition, or `null` to disable the rule.\n *\n * See [twitter mentions example](https://github.com/markdown-it/linkify-it/blob/master/examples/twitter.mjs).\n */\n add (schema: string, definition: SchemaOpts | null = null): this {\n if (!definition) {\n delete this.__schemas__[schema]\n } else {\n const def = {\n normalize: (match: Match, self: LinkifyIt) => self.normalize(match),\n ...definition\n }\n this.__schemas__[schema] = def\n }\n\n this.re.set({\n ...this.__opts__,\n schema_names: Object.keys(this.__schemas__)\n })\n return this\n }\n\n /**\n * Set recognition options for links without schema.\n *\n * @param options Recognition options.\n */\n set (options: LinkifyOptions = {}): this {\n this.__opts__ = { ...this.__opts__, ...options }\n this.re.set({\n ...this.__opts__,\n schema_names: Object.keys(this.__schemas__)\n })\n return this\n }\n\n /**\n * Searches linkifiable pattern and returns `true` on success or `false` on fail.\n *\n * @param text Text to scan.\n */\n test (text: string): boolean {\n if (!text.length) { return false }\n\n let m, re\n\n // try to scan for link with schema - that's the most simple rule\n re = this.re.get_schema_search()\n re.lastIndex = 0\n while ((m = re.exec(text)) !== null) {\n if (this.testSchemaAt(text, m[2], re.lastIndex)) { return true }\n }\n\n if (this.__opts__.fuzzyLink && this.__schemas__['http:']) {\n // guess schemaless links\n re = this.re.get_fuzzy_link_search()\n re.lastIndex = 0\n if (re.exec(text) !== null) { return true }\n }\n\n if (this.__opts__.fuzzyEmail && this.__schemas__['mailto:']) {\n // guess schemaless emails\n if (text.indexOf('@') >= 0) {\n // We can't skip this check, because this cases are possible:\n // 192.168.1.1@gmail.com, my.in@example.com\n const mailHostRe = this.re.get_fuzzy_mail_host_search()\n const mailNameRe = this.re.get_mail_name_validator()\n mailHostRe.lastIndex = 0\n\n while ((m = mailHostRe.exec(text)) !== null) {\n const name = text.slice(Math.max(0, m.index - 65), m.index)\n if (mailNameRe.test(name)) { return true }\n }\n }\n }\n\n return false\n }\n\n /**\n * Similar to {@link LinkifyIt.test} but checks only specific protocol tail exactly\n * at given position. Returns length of found pattern (0 on fail).\n *\n * @param text Text to scan.\n * @param schema Rule (schema) name.\n * @param pos Text offset to check from.\n */\n testSchemaAt (text: string, schema: string, pos: number): number {\n // If not supported schema check requested - terminate\n if (!this.__schemas__[schema.toLowerCase()]) { return 0 }\n\n return this.__schemas__[schema.toLowerCase()].validate(\n text.slice(0, pos + this.__opts__.maxLength),\n pos,\n this\n )\n }\n\n /**\n * Returns array of found link descriptions or `null` on fail. We strongly\n * recommend to use {@link LinkifyIt.test} first, for best speed.\n *\n * @param text Text to scan.\n */\n match (text: string): Match[] | null {\n const result: Match[] = []\n const schemaRe = this.re.get_schema_search()\n let fuzzyLinkRe: RegExp | undefined\n let mailHostRe: RegExp | undefined\n let mailNameRe: RegExp | undefined\n let fuzzyLinkCandidate: MatchCandidate | undefined\n let fuzzyEmailCandidate: MatchCandidate | undefined\n let schemaPrefix: MatchCandidate | undefined\n let schemaDone = false\n let fuzzyLinkDone = false\n let fuzzyEmailDone = false\n let pos = 0\n\n if (!text.length) { return null }\n\n schemaRe.lastIndex = 0\n\n if (this.__opts__.fuzzyLink && this.__schemas__['http:']) {\n fuzzyLinkRe = this.re.get_fuzzy_link_search()\n fuzzyLinkRe.lastIndex = 0\n }\n\n if (this.__opts__.fuzzyEmail && this.__schemas__['mailto:']) {\n mailHostRe = this.re.get_fuzzy_mail_host_search()\n mailHostRe.lastIndex = 0\n mailNameRe = this.re.get_mail_name_validator()\n }\n\n for (;;) {\n const scanFrom = Math.max(pos - 1, 0)\n\n if (mailHostRe && mailNameRe && !fuzzyEmailDone && (!fuzzyEmailCandidate || fuzzyEmailCandidate.index < pos)) {\n if (mailHostRe.lastIndex < scanFrom) { mailHostRe.lastIndex = scanFrom }\n\n for (;;) {\n const m = mailHostRe.exec(text)\n if (!m) {\n fuzzyEmailDone = true\n fuzzyEmailCandidate = undefined\n break\n }\n\n const name = mailNameRe.exec(text.slice(Math.max(0, m.index - 65), m.index))\n if (!name) { continue }\n\n fuzzyEmailCandidate = {\n schema: 'mailto:',\n index: m.index - name[1].length,\n lastIndex: m.index + m[0].length\n }\n\n if (fuzzyEmailCandidate.index >= pos) { break }\n if (mailHostRe.lastIndex < scanFrom) { mailHostRe.lastIndex = scanFrom }\n }\n }\n\n if (fuzzyLinkRe && !fuzzyLinkDone && (!fuzzyLinkCandidate || fuzzyLinkCandidate.index < pos)) {\n if (fuzzyLinkRe.lastIndex < scanFrom) { fuzzyLinkRe.lastIndex = scanFrom }\n\n for (;;) {\n const m = fuzzyLinkRe.exec(text)\n if (!m) {\n fuzzyLinkDone = true\n fuzzyLinkCandidate = undefined\n break\n }\n\n fuzzyLinkCandidate = {\n schema: '',\n index: m.index + m[1].length,\n lastIndex: m.index + m[0].length\n }\n\n if (fuzzyLinkCandidate.index >= pos) { break }\n if (fuzzyLinkRe.lastIndex < scanFrom) { fuzzyLinkRe.lastIndex = scanFrom }\n }\n }\n\n let fuzzyCandidate = fuzzyEmailCandidate\n if (!fuzzyCandidate ||\n (fuzzyLinkCandidate &&\n (fuzzyLinkCandidate.index < fuzzyCandidate.index ||\n (fuzzyLinkCandidate.index === fuzzyCandidate.index && fuzzyLinkCandidate.lastIndex > fuzzyCandidate.lastIndex)))) {\n fuzzyCandidate = fuzzyLinkCandidate\n }\n\n let schemaCandidate: MatchCandidate | undefined\n\n if (!schemaDone) {\n for (;;) {\n if (!schemaPrefix) {\n if (schemaRe.lastIndex < scanFrom) { schemaRe.lastIndex = scanFrom }\n\n const m = schemaRe.exec(text)\n if (!m) {\n schemaDone = true\n break\n }\n\n schemaPrefix = {\n schema: m[2],\n index: m.index + m[1].length,\n lastIndex: m.index + m[0].length\n }\n }\n\n if (schemaPrefix.index < pos) {\n schemaPrefix = undefined\n continue\n }\n\n if (fuzzyCandidate && schemaPrefix.index > fuzzyCandidate.index) { break }\n\n const prefix = schemaPrefix\n schemaPrefix = undefined\n\n const len = this.testSchemaAt(text, prefix.schema, prefix.lastIndex)\n if (len) {\n schemaCandidate = {\n schema: prefix.schema,\n index: prefix.index,\n lastIndex: prefix.lastIndex + len\n }\n break\n }\n }\n }\n\n let candidate = schemaCandidate\n if (!candidate ||\n (fuzzyEmailCandidate &&\n (fuzzyEmailCandidate.index < candidate.index ||\n (fuzzyEmailCandidate.index === candidate.index && fuzzyEmailCandidate.lastIndex > candidate.lastIndex)))) {\n candidate = fuzzyEmailCandidate\n }\n if (!candidate ||\n (fuzzyLinkCandidate &&\n (fuzzyLinkCandidate.index < candidate.index ||\n (fuzzyLinkCandidate.index === candidate.index && fuzzyLinkCandidate.lastIndex > candidate.lastIndex)))) {\n candidate = fuzzyLinkCandidate\n }\n\n if (!candidate) { break }\n\n if (candidate === fuzzyEmailCandidate) {\n fuzzyEmailCandidate = undefined\n } else if (candidate === fuzzyLinkCandidate) {\n fuzzyLinkCandidate = undefined\n }\n\n const match = new Match(text, candidate.schema, candidate.index, candidate.lastIndex)\n if (match.schema) {\n this.__schemas__[match.schema].normalize(match, this)\n } else {\n this.normalize(match)\n }\n result.push(match)\n pos = candidate.lastIndex\n }\n\n if (result.length) {\n return result\n }\n\n return null\n }\n\n /**\n * Returns fully-formed (not fuzzy) link if it starts at the beginning\n * of the string, and null otherwise.\n *\n * @param text Text to scan.\n */\n matchAtStart (text: string): Match | null {\n if (!text.length) return null\n\n const m = this.re.get_schema_at_start().exec(text)\n if (!m) return null\n\n const len = this.testSchemaAt(text, m[2], m[0].length)\n if (!len) return null\n\n const match = new Match(text, m[2], m.index + m[1].length, m.index + m[0].length + len)\n\n this.__schemas__[match.schema].normalize(match, this)\n return match\n }\n\n /**\n * Load (or merge) new TLDs list. Those are used for fuzzy links (without\n * prefix) to avoid false positives. By default this algorithm is used:\n *\n * - hostname with any 2-letter root zones are ok.\n * - biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф\n * are ok.\n * - encoded (`xn--...`) root zones are ok.\n *\n * If list is replaced, then exact match for 2-chars root zones will be checked.\n *\n * @param list List of TLDs.\n * @param keepOld Merge with current list if `true` (`false` by default).\n */\n tlds (list: string | string[], keepOld = false): this {\n list = Array.isArray(list) ? list : [list]\n\n if (!keepOld) {\n this.__opts__.tlds = list\n } else {\n this.__opts__.tlds = this.__opts__.tlds.concat(list)\n }\n\n this.re.set({\n ...this.__opts__,\n schema_names: Object.keys(this.__schemas__)\n })\n return this\n }\n\n /**\n * Default normalizer (if schema does not define its own).\n *\n * @param match Match to normalize.\n */\n normalize (match: Match): void {\n // Do minimal possible changes by default. Need to collect feedback prior\n // to move forward https://github.com/markdown-it/linkify-it/issues/1\n\n if (!match.schema) { match.url = `http://${match.url}` }\n\n if (match.schema === 'mailto:' && !/^mailto:/i.test(match.url)) {\n match.url = `mailto:${match.url}`\n }\n }\n}\n\nfunction linkifyit (options: LinkifyConstructorOptions = {}): LinkifyIt {\n return new LinkifyIt(options)\n}\n\nexport { linkifyit }\n"],"mappings":"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"} |
+236
| /** | ||
| * @category types | ||
| */ | ||
| interface REBuilderOptions { | ||
| '---'?: boolean; | ||
| fuzzyIP?: boolean; | ||
| schema_names?: string[]; | ||
| tlds?: string[]; | ||
| urlAuth?: boolean; | ||
| maxLength?: number; | ||
| } | ||
| declare class REBuilder { | ||
| src_Any: string; | ||
| src_Cc: string; | ||
| src_Z: string; | ||
| src_P: string; | ||
| src_ZPCc: string; | ||
| src_ZCc: string; | ||
| cache: Record<string, RegExp | undefined>; | ||
| opts: REBuilderOptions; | ||
| constructor(opts?: REBuilderOptions); | ||
| set(opts?: REBuilderOptions): this; | ||
| escapeRE(str: string): string; | ||
| nestedPairRE(open: string, close: string, depth?: number): string; | ||
| get_text_separators(): RegExp; | ||
| get_pseudo_letter(): RegExp; | ||
| get_ipv4_addr(): RegExp; | ||
| get_ipv6_addr(): RegExp; | ||
| get_ipv6_url_host(): RegExp; | ||
| get_ipv6_mail_host(): RegExp; | ||
| get_auth(): RegExp; | ||
| get_port(): RegExp; | ||
| get_host_terminator(): RegExp; | ||
| get_path_terminator(): RegExp; | ||
| get_path(): RegExp; | ||
| get_mail_name(): RegExp; | ||
| get_xn(): RegExp; | ||
| get_tld(): RegExp; | ||
| get_domain_root(): RegExp; | ||
| get_domain(): RegExp; | ||
| get_url_host_port(): RegExp; | ||
| get_fuzzy_url_host_port(): RegExp; | ||
| get_mail_host(): RegExp; | ||
| get_fuzzy_mail_host(): RegExp; | ||
| get_path_extra(): RegExp; | ||
| get_fuzzy_mail_host_search(): RegExp; | ||
| get_fuzzy_link_search(): RegExp; | ||
| get_http_validator(): RegExp; | ||
| get_relative_proto_validator(): RegExp; | ||
| get_mail_name_validator(): RegExp; | ||
| get_mailto_validator(): RegExp; | ||
| get_schema_names(): RegExp; | ||
| get_schema_search(): RegExp; | ||
| get_schema_at_start(): RegExp; | ||
| } | ||
| /** | ||
| * Recognition options for schemaless links. | ||
| * | ||
| * @category types | ||
| */ | ||
| interface LinkifyOptions { | ||
| /** Recognize URLs without `http(s)://` prefix. Default `false`. */ | ||
| fuzzyLink?: boolean; | ||
| /** Recognize emails without `mailto:` prefix. Default `true`. */ | ||
| fuzzyEmail?: boolean; | ||
| /** | ||
| * Allow IPs in fuzzy links. Can conflict with some texts, like version | ||
| * numbers. Default `false`. | ||
| */ | ||
| fuzzyIP?: boolean; | ||
| /** | ||
| * Terminate link with `---` if it is considered a long dash. Default `false`. | ||
| */ | ||
| '---'?: boolean; | ||
| /** Allowed TLDs list for fuzzy links. Replaces the default list when set. */ | ||
| tlds?: string[]; | ||
| /** Recognize authentication data in URLs. Default `false`. */ | ||
| urlAuth?: boolean; | ||
| /** Maximum link length. Default `10000`. */ | ||
| maxLength?: number; | ||
| } | ||
| interface LinkifyConstructorOptions extends LinkifyOptions { | ||
| /** Custom regular expression builder. */ | ||
| rebuilder?: REBuilder; | ||
| } | ||
| /** | ||
| * Custom schema definition. | ||
| * | ||
| * @category types | ||
| */ | ||
| interface SchemaOpts { | ||
| /** | ||
| * Checks text after the schema prefix. Should return matched tail length on | ||
| * success, or `0` on fail. | ||
| */ | ||
| validate: (text: string, pos: number, self: LinkifyIt) => number; | ||
| /** | ||
| * Optional function to normalize `text` and `url` of matched result, for | ||
| * example for `@twitter` mentions. | ||
| */ | ||
| normalize?: (match: Match, self: LinkifyIt) => void; | ||
| } | ||
| /** | ||
| * Match result returned by {@link LinkifyIt.match} and | ||
| * {@link LinkifyIt.matchAtStart}. | ||
| * | ||
| * @category types | ||
| */ | ||
| declare class Match { | ||
| /** Prefix (protocol) for matched string. Empty for fuzzy links. */ | ||
| schema: string; | ||
| /** First position of matched string. */ | ||
| index: number; | ||
| /** Next position after matched string. */ | ||
| lastIndex: number; | ||
| /** Matched string. */ | ||
| raw: string; | ||
| /** Normalized text of matched string. */ | ||
| text: string; | ||
| /** Normalized URL of matched string. */ | ||
| url: string; | ||
| constructor(text: string, schema: string, index: number, lastIndex: number); | ||
| } | ||
| /** Linkifier instance. */ | ||
| declare class LinkifyIt { | ||
| __opts__: Required<LinkifyOptions>; | ||
| private __schemas__; | ||
| re: REBuilder; | ||
| /** | ||
| * 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?: LinkifyConstructorOptions); | ||
| /** | ||
| * 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: string, definition?: SchemaOpts | null): this; | ||
| /** | ||
| * Set recognition options for links without schema. | ||
| * | ||
| * @param options Recognition options. | ||
| */ | ||
| set(options?: LinkifyOptions): this; | ||
| /** | ||
| * Searches linkifiable pattern and returns `true` on success or `false` on fail. | ||
| * | ||
| * @param text Text to scan. | ||
| */ | ||
| test(text: string): boolean; | ||
| /** | ||
| * 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: string, schema: string, pos: number): number; | ||
| /** | ||
| * 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: string): Match[] | 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: string): Match | null; | ||
| /** | ||
| * 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: string | string[], keepOld?: boolean): this; | ||
| /** | ||
| * Default normalizer (if schema does not define its own). | ||
| * | ||
| * @param match Match to normalize. | ||
| */ | ||
| normalize(match: Match): void; | ||
| } | ||
| declare function linkifyit(options?: LinkifyConstructorOptions): LinkifyIt; | ||
| export { LinkifyIt, Match, REBuilder, linkifyit }; | ||
| export type { LinkifyConstructorOptions, LinkifyOptions, REBuilderOptions, SchemaOpts }; |
+538
| import { Any, Cc, P, Z } from "uc.micro"; | ||
| //#region src/rebuilder.ts | ||
| 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"); | ||
| } | ||
| }; | ||
| //#endregion | ||
| //#region src/linkifyit.ts | ||
| 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}`; | ||
| } | ||
| }; | ||
| function linkifyit(options = {}) { | ||
| return new LinkifyIt(options); | ||
| } | ||
| //#endregion | ||
| export { LinkifyIt, REBuilder, linkifyit }; | ||
| //# sourceMappingURL=index.mjs.map |
| {"version":3,"file":"index.mjs","names":[],"sources":["../src/rebuilder.ts","../src/linkifyit.ts"],"sourcesContent":["/* eslint-disable no-return-assign, prefer-regex-literals */\n\nimport { Any, Cc, Z, P } from 'uc.micro'\n\n/**\n * @category types\n */\nexport interface REBuilderOptions {\n '---'?: boolean\n fuzzyIP?: boolean\n schema_names?: string[]\n tlds?: string[]\n urlAuth?: boolean\n maxLength?: number\n}\n\nexport class REBuilder {\n src_Any = Any.source\n src_Cc = Cc.source\n src_Z = Z.source\n src_P = P.source\n // \\p{\\Z\\P\\Cc\\CF} (white spaces + control + format + punctuation)\n src_ZPCc = [this.src_Z, this.src_P, this.src_Cc].join('|')\n // \\p{\\Z\\Cc} (white spaces + control)\n src_ZCc = [this.src_Z, this.src_Cc].join('|')\n cache: Record<string, RegExp | undefined> = {}\n opts: REBuilderOptions = { maxLength: 10000, urlAuth: false, schema_names: [] }\n\n constructor (opts: REBuilderOptions = {}) {\n this.opts = { ...this.opts, ...opts }\n }\n\n set (opts: REBuilderOptions = {}) {\n this.opts = { ...this.opts, ...opts }\n\n this.cache = {}\n return this\n }\n\n escapeRE (str: string) { return str.replace(/[.?*+^$[\\]\\\\(){}|-]/g, '\\\\$&') }\n\n nestedPairRE (open: string, close: string, depth = 4) {\n const openRE = this.escapeRE(open)\n const closeRE = this.escapeRE(close)\n const atom = `(?:(?!${this.src_ZCc}|${openRE}|${closeRE}).)`\n\n let pair = `${openRE}${atom}{0,1000}${closeRE}`\n\n for (let level = 2; level <= depth; level++) {\n pair = `${openRE}(?:${atom}|${pair}){0,1000}${closeRE}`\n }\n\n return pair\n }\n\n // Partials\n\n get_text_separators () {\n // Experimental. List of chars, completely prohibited in links\n // because can separate it from other part of text\n return this.cache.text_separators ??= /[><\\uff5c]/\n }\n\n get_pseudo_letter () {\n return this.cache.src_pseudo_letter ??= new RegExp(\n // All possible word characters (everything without punctuation, spaces & controls)\n // Defined via punctuation & spaces to save space\n // Should be something like \\p{\\L\\N\\S\\M} (\\w but without `_`)\n `(?:(?!${this.get_text_separators().source}|${this.src_ZPCc})${this.src_Any})`\n )\n }\n\n get_ipv4_addr () {\n return this.cache.src_ip4 ??= new RegExp(\n '(?:' +\n '(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])[.]' +\n '){3}' +\n '(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])'\n )\n }\n\n get_ipv6_addr () {\n const h16 = '[0-9A-Fa-f]{1,4}'\n const ls32 = `(?:(?:${h16}:${h16})|${this.get_ipv4_addr().source})`\n\n return this.cache.src_ip6_addr ??= new RegExp(\n '(?:' +\n `(?:${h16}:){6}${ls32}|` +\n `::(?:${h16}:){5}${ls32}|` +\n `(?:${h16})?::(?:${h16}:){4}${ls32}|` +\n `(?:(?:${h16}:){0,1}${h16})?::(?:${h16}:){3}${ls32}|` +\n `(?:(?:${h16}:){0,2}${h16})?::(?:${h16}:){2}${ls32}|` +\n `(?:(?:${h16}:){0,3}${h16})?::${h16}:${ls32}|` +\n `(?:(?:${h16}:){0,4}${h16})?::${ls32}|` +\n `(?:(?:${h16}:){0,5}${h16})?::${h16}|` +\n `(?:(?:${h16}:){0,6}${h16})?::` +\n ')'\n )\n }\n\n get_ipv6_url_host () {\n return this.cache.src_ip6_host ??= new RegExp(\n `\\\\[${this.get_ipv6_addr().source}\\\\]`\n )\n }\n\n get_ipv6_mail_host () {\n return this.cache.src_ipv6_mail_host ??= new RegExp(\n `\\\\[IPv6:${this.get_ipv6_addr().source}\\\\]`\n )\n }\n\n get_auth () {\n return this.cache.src_auth ??= new RegExp(\n // Prohibit any of \"@/[]()\" in user/pass to avoid wrong domain fetch.\n // Length is capped to exclude possible rescans till the end and avoid O(n^2)\n // DoS. No standard limit, just take something reasonable.\n `(?:(?:(?!${this.src_ZCc}|[@/\\\\[\\\\]()]).){1,50}@)?`\n )\n }\n\n get_port () {\n return this.cache.src_port ??= new RegExp(\n '(?::(?:6(?:[0-4]\\\\d{3}|5(?:[0-4]\\\\d{2}|5(?:[0-2]\\\\d|3[0-5])))|[1-5]?\\\\d{1,4}))?'\n )\n }\n\n get_host_terminator () {\n // Force greedy fetch, we should not stop earlier than host part is fully fetched.\n return this.cache.src_host_terminator ??= new RegExp(\n `(?=$|${this.get_text_separators().source}|${this.src_ZPCc})` +\n `(?!${this.opts['---'] ? '-(?!--)|' : '-|'}_|:\\\\d|\\\\.-|\\\\.(?!$|${this.src_ZPCc}))`\n )\n }\n\n get_path_terminator () {\n return this.cache.src_path_terminator ??= new RegExp(\n `${this.src_ZPCc}|${this.get_text_separators().source}`\n // `${this.src_ZCc}|${this.get_text_separators().source}|[()[\\\\]{}.,\"'?!\\\\-;]`\n )\n }\n\n get_path () {\n return this.cache.src_path ??= new RegExp(\n '(?:' +\n '[/?#]' +\n '(?:' +\n `${this.nestedPairRE('[', ']')}|` +\n `${this.nestedPairRE('(', ')')}|` +\n `${this.nestedPairRE('{', '}')}|` +\n `\\\\\"(?:(?!${this.src_ZCc}|[\"]).){1,100}\\\\\"|` +\n `\\\\'(?:(?!${this.src_ZCc}|[']).){1,100}\\\\'|` +\n\n // allow `I'm_king` if no pair found\n `\\\\'(?=${this.get_pseudo_letter().source}|[-])|` +\n\n // 1. google has many dots in \"google search\" links (#66, #81).\n // github has ... in commit range links,\n // Restrict to\n // - english\n // - percent-encoded\n // - parts of file path\n // - params separator\n // until more examples found.\n //\n // 2. Allow `..:XX` for Odysee links (optional `:`), #100\n // This may be narrowed down later via separate rule.\n '\\\\.{2,20}[:]?[a-zA-Z0-9%/&]|' +\n\n `\\\\.(?!${this.src_ZCc}|[.]|$)|` +\n (this.opts['---']\n ? '\\\\-(?!--(?:[^-]|$))(?:-{0,19})|' // `---` => long dash, terminate\n : '\\\\-{1,20}|'\n ) +\n // allow `,,,` in paths\n `,(?!${this.src_ZCc}|$)|` +\n\n // allow `;` if not followed by space-like char\n `;(?!${this.src_ZCc}|$)|` +\n\n // allow `!!!` in paths, but not at the end\n `\\\\!{1,20}(?!${this.src_ZCc}|[!]|$)|` +\n\n `\\\\?(?!${this.src_ZCc}|[?]|$)|` +\n\n this.get_path_extra().source +\n\n // allowed punctuation chars in path.\n '[\\\\\\\\/:%@#&=_~*]|' +\n\n // if no special rules matched, consume all chars except terminators.\n `(?!${this.get_path_terminator().source}).` +\n `){1,${this.opts.maxLength}}` +\n '|\\\\/' +\n ')?'\n )\n }\n\n get_mail_name () {\n return this.cache.src_mail_name ??= new RegExp(\n // RFC 5321 dot-string only (no quoted-string), max 64 ASCII characters.\n \"[-!#$%&'*+/=?^_`{|}~a-zA-Z0-9](?:[-!#$%&'*+/=?^_`{|}~a-zA-Z0-9]|[.](?=[-!#$%&'*+/=?^_`{|}~a-zA-Z0-9])){0,63}\"\n )\n }\n\n get_xn () {\n return this.cache.src_xn ??= new RegExp(\n 'xn--[a-z0-9\\\\-]{1,59}'\n )\n }\n\n get_tld () {\n if (this.cache.tld) return this.cache.tld\n\n const tlds_src = [...new Set(this.opts.tlds || [])].sort().reverse()\n .join('|')\n\n this.cache.tld = new RegExp(\n `${tlds_src || '$#none#$'}|${this.get_xn().source}`\n )\n return this.cache.tld\n }\n\n get_domain_root () {\n return this.cache.src_domain_root ??= new RegExp(\n // More to read about domain names\n // http://serverfault.com/questions/638260/\n\n // Allow letters & digits (http://test1)\n '(?:' +\n this.get_xn().source +\n '|' +\n `${this.get_pseudo_letter().source}{1,63}` +\n ')'\n )\n }\n\n get_domain () {\n return this.cache.src_domain ??= new RegExp(\n '(?:' +\n this.get_xn().source +\n '|' +\n `(?:${this.get_pseudo_letter().source})` +\n '|' +\n `(?:${this.get_pseudo_letter().source}(?:-|${this.get_pseudo_letter().source}){0,61}${this.get_pseudo_letter().source})` +\n ')'\n )\n }\n\n // Host rules, depending on the type\n\n get_url_host_port () {\n return this.cache.url_host_port ??= new RegExp(\n '(?:' +\n // Don't need IP v4 check, because digits are already allowed\n // in normal domain names\n this.get_ipv6_url_host().source +\n '|' +\n `(?:(?:(?:${this.get_domain().source})\\\\.){0,10}${this.get_domain().source})`/* _root */ +\n ')' +\n this.get_port().source +\n this.get_host_terminator().source\n )\n }\n\n get_fuzzy_url_host_port () {\n // - TLD as anchor\n // - No local domains\n return this.cache.fuzzy_url_host_port ??= new RegExp(\n '(?:' +\n (this.opts.fuzzyIP ? this.get_ipv4_addr().source + '|' : '') +\n `(?:(?:(?:${this.get_domain().source})\\\\.){1,10}(?:${this.get_tld().source}))` +\n ')' +\n // No port in fuzzy links to reduce search\n this.get_host_terminator().source\n )\n }\n\n get_mail_host () {\n // Similar to normal url host, but\n // - with different ipv6 format (and without port).\n // - with reduced max subdomains\n return this.cache.src_mail_host ??= new RegExp(\n '(?:' +\n this.get_ipv6_mail_host().source +\n '|' +\n `(?:(?:(?:${this.get_domain().source})\\\\.){0,4}${this.get_domain().source})` +\n ')' +\n this.get_host_terminator().source\n )\n }\n\n get_fuzzy_mail_host () {\n // Similar to normal mail host, but without local domains.\n return this.cache.src_fuzzy_mail_host ??= new RegExp(\n '(?:' +\n this.get_ipv6_mail_host().source +\n '|' +\n `(?:(?:(?:${this.get_domain().source})[.]){1,4}${this.get_domain_root().source})` +\n ')' +\n this.get_host_terminator().source\n )\n }\n\n // Hooks\n\n get_path_extra () {\n return this.cache.src_path_extra ??= new RegExp('')\n }\n\n // \"Public\" rules\n\n get_fuzzy_mail_host_search () {\n return this.cache.mail_fuzzy_host_search ??= new RegExp(\n `@${this.get_fuzzy_mail_host().source}`,\n 'ig'\n )\n }\n\n get_fuzzy_link_search () {\n return this.cache.link_fuzzy_search ??= new RegExp(\n // Fuzzy link can't be prepended with .:/\\- and non punctuation.\n // but can start with > (markdown blockquote)\n `(^|(?![.:/\\\\-_@])(?:[$+<=>^\\`|\\uff5c]|${this.src_ZPCc}))` +\n `(?:(?![$+<=>^\\`|\\uff5c])${this.get_fuzzy_url_host_port().source}${this.get_path().source})`,\n 'ig'\n )\n }\n\n get_http_validator () {\n return this.cache.http_validator ??= new RegExp(\n '\\\\/\\\\/' +\n (this.opts.urlAuth ? this.get_auth().source : '') +\n this.get_url_host_port().source +\n this.get_path().source,\n 'iy'\n )\n }\n\n get_relative_proto_validator () {\n return this.cache.relative_proto_validator ??= new RegExp(\n (this.opts.urlAuth ? this.get_auth().source : '') +\n // Don't allow single-level domains, because of false positives like '//test'\n // with code comments.\n `(?:localhost|${this.get_ipv6_url_host().source}|(?:(?:${this.get_domain().source})[.]){1,10}${this.get_domain_root().source})` +\n this.get_port().source +\n this.get_host_terminator().source +\n this.get_path().source,\n\n 'iy'\n )\n }\n\n get_mail_name_validator () {\n return this.cache.mail_name_validator ??= new RegExp(\n `(?:^|${this.get_text_separators().source}|\"|\\\\(|${this.src_ZCc})` +\n `(${this.get_mail_name().source})$`\n )\n }\n\n get_mailto_validator () {\n return this.cache.mailto_validator ??= new RegExp(\n `${this.get_mail_name().source}@${this.get_mail_host().source}`,\n 'iy'\n )\n }\n\n get_schema_names () {\n return this.cache.schema_names ??= new RegExp((this.opts.schema_names || []).map(name => this.escapeRE(name)).join('|'))\n }\n\n get_schema_search () {\n return this.cache.schema_search ??= new RegExp(\n `(^|(?!_)(?:[><\\uff5c]|${this.src_ZPCc}))(${this.get_schema_names().source})`,\n 'ig'\n )\n }\n\n get_schema_at_start () {\n return this.cache.schema_at_start ??= new RegExp(\n `^${this.get_schema_search().source}`,\n 'i'\n )\n }\n}\n","import { REBuilder } from './rebuilder.ts'\n\n//\n\n/**\n * Recognition options for schemaless links.\n *\n * @category types\n */\nexport interface LinkifyOptions {\n /** Recognize URLs without `http(s)://` prefix. Default `false`. */\n fuzzyLink?: boolean\n /** Recognize emails without `mailto:` prefix. Default `true`. */\n fuzzyEmail?: boolean\n /**\n * Allow IPs in fuzzy links. Can conflict with some texts, like version\n * numbers. Default `false`.\n */\n fuzzyIP?: boolean\n /**\n * Terminate link with `---` if it is considered a long dash. Default `false`.\n */\n '---'?: boolean\n /** Allowed TLDs list for fuzzy links. Replaces the default list when set. */\n tlds?: string[]\n /** Recognize authentication data in URLs. Default `false`. */\n urlAuth?: boolean\n /** Maximum link length. Default `10000`. */\n maxLength?: number\n}\n\nexport interface LinkifyConstructorOptions extends LinkifyOptions {\n /** Custom regular expression builder. */\n rebuilder?: REBuilder\n}\n\n/**\n * Custom schema definition.\n *\n * @category types\n */\nexport interface SchemaOpts {\n /**\n * Checks text after the schema prefix. Should return matched tail length on\n * success, or `0` on fail.\n */\n validate: (text: string, pos: number, self: LinkifyIt) => number\n /**\n * Optional function to normalize `text` and `url` of matched result, for\n * example for `@twitter` mentions.\n */\n normalize?: (match: Match, self: LinkifyIt) => void\n}\n\ntype Schema = Required<SchemaOpts>\n\ninterface MatchCandidate {\n schema: string\n index: number\n lastIndex: number\n}\n\nconst web_schema: Schema = {\n validate: (text: string, pos: number, self: LinkifyIt) => {\n const re = self.re.get_http_validator()\n re.lastIndex = pos\n\n const m = re.exec(text)\n return m ? m[0].length : 0\n },\n normalize: (match: Match, self: LinkifyIt) => self.normalize(match)\n}\n\nconst defaultSchemas: Record<string, Schema> = {\n 'http:': web_schema,\n 'https:': web_schema,\n 'ftp:': web_schema,\n '//': {\n validate: function (text: string, pos: number, self: LinkifyIt) {\n const re = self.re.get_relative_proto_validator()\n re.lastIndex = pos\n\n const m = re.exec(text)\n if (m) {\n // should not be `://` & `///`, that protects from errors in protocol name\n if (pos >= 3 && text[pos - 3] === ':') { return 0 }\n if (pos >= 3 && text[pos - 3] === '/') { return 0 }\n return m[0].length\n }\n return 0\n },\n normalize: (match: Match, self: LinkifyIt) => self.normalize(match)\n },\n 'mailto:': {\n validate: function (text: string, pos: number, self: LinkifyIt) {\n const re = self.re.get_mailto_validator()\n re.lastIndex = pos\n\n const m = re.exec(text)\n return m ? m[0].length : 0\n },\n normalize: (match: Match, self: LinkifyIt) => self.normalize(match)\n }\n}\n\n// List of 2-character tlds (autogenerated by ./support/tlds_2char_gen.js)\nconst 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'\n\n// DON'T try to make PRs with changes. Extend TLDs with LinkifyIt.tlds() instead\nconst tlds_default = 'biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф'\n\nfunction unpackTlds (): string[] {\n const result = tlds_default.split('|')\n\n tlds_2ch.split('|').forEach((item) => {\n const sep = item.indexOf(':')\n\n const prefix = item.slice(0, sep)\n\n for (const suffix of item.slice(sep + 1)) {\n result.push(prefix + suffix)\n }\n })\n\n return result\n}\n\nconst defaultOptions: Required<LinkifyOptions> = {\n fuzzyLink: false,\n fuzzyEmail: true,\n fuzzyIP: false,\n '---': false,\n tlds: unpackTlds(),\n urlAuth: false,\n maxLength: 10000\n}\n\n/**\n * Match result returned by {@link LinkifyIt.match} and\n * {@link LinkifyIt.matchAtStart}.\n *\n * @category types\n */\nexport class Match {\n /** Prefix (protocol) for matched string. Empty for fuzzy links. */\n schema: string\n /** First position of matched string. */\n index: number\n /** Next position after matched string. */\n lastIndex: number\n /** Matched string. */\n raw: string\n /** Normalized text of matched string. */\n text: string\n /** Normalized URL of matched string. */\n url: string\n\n constructor (text: string, schema: string, index: number, lastIndex: number) {\n const raw = text.slice(index, lastIndex)\n\n this.schema = schema.toLowerCase()\n this.index = index\n this.lastIndex = lastIndex\n this.raw = raw\n this.text = raw\n this.url = raw\n }\n}\n\n/** Linkifier instance. */\nexport class LinkifyIt {\n __opts__: Required<LinkifyOptions>\n private __schemas__: Record<string, Schema>\n re: REBuilder\n\n /**\n * Creates new linkifier instance.\n *\n * By default understands:\n *\n * - `http(s)://...` , `ftp://...`, `mailto:...` & `//...` links\n * - \"fuzzy\" emails (foo@bar.com).\n *\n * See {@link LinkifyConstructorOptions} for available options.\n *\n * @param options Recognition options.\n *\n * @example\n * ```javascript\n * import { LinkifyIt } from 'linkify-it'\n *\n * const linkify = new LinkifyIt({ fuzzyLink: true })\n *\n * linkify\n * .tlds(require('tlds')) // Reload with full TLD list\n * .tlds('onion', true) // Add unofficial `.onion` domain\n * .add('ftp:', null) // Disable `ftp:` protocol\n * .set({ fuzzyIP: true }) // Enable IPs in fuzzy links\n *\n * console.log(linkify.test('Site github.com!')) // true\n * console.log(linkify.match('Site github.com!'))\n * ```\n */\n constructor (options: LinkifyConstructorOptions = {}) {\n const { rebuilder, ...linkifyOptions } = options\n\n this.__opts__ = { ...defaultOptions, ...linkifyOptions }\n\n this.__schemas__ = { ...defaultSchemas }\n\n this.re = rebuilder || new REBuilder()\n this.re.set({\n ...this.__opts__,\n schema_names: Object.keys(this.__schemas__)\n })\n }\n\n /**\n * Add new rule definition.\n *\n * `schema` is a link prefix (usually, protocol name with `:` at the end,\n * `skype:` for example). `linkify-it` makes sure that prefix is not\n * preceded with alphanumeric char and symbols. Only whitespaces and\n * punctuation allowed.\n *\n * `definition` is a rule to check tail after link prefix. To disable an\n * existing rule, pass `null`.\n *\n * @param schema Rule name (fixed pattern prefix).\n * @param definition Schema definition, or `null` to disable the rule.\n *\n * See [twitter mentions example](https://github.com/markdown-it/linkify-it/blob/master/examples/twitter.mjs).\n */\n add (schema: string, definition: SchemaOpts | null = null): this {\n if (!definition) {\n delete this.__schemas__[schema]\n } else {\n const def = {\n normalize: (match: Match, self: LinkifyIt) => self.normalize(match),\n ...definition\n }\n this.__schemas__[schema] = def\n }\n\n this.re.set({\n ...this.__opts__,\n schema_names: Object.keys(this.__schemas__)\n })\n return this\n }\n\n /**\n * Set recognition options for links without schema.\n *\n * @param options Recognition options.\n */\n set (options: LinkifyOptions = {}): this {\n this.__opts__ = { ...this.__opts__, ...options }\n this.re.set({\n ...this.__opts__,\n schema_names: Object.keys(this.__schemas__)\n })\n return this\n }\n\n /**\n * Searches linkifiable pattern and returns `true` on success or `false` on fail.\n *\n * @param text Text to scan.\n */\n test (text: string): boolean {\n if (!text.length) { return false }\n\n let m, re\n\n // try to scan for link with schema - that's the most simple rule\n re = this.re.get_schema_search()\n re.lastIndex = 0\n while ((m = re.exec(text)) !== null) {\n if (this.testSchemaAt(text, m[2], re.lastIndex)) { return true }\n }\n\n if (this.__opts__.fuzzyLink && this.__schemas__['http:']) {\n // guess schemaless links\n re = this.re.get_fuzzy_link_search()\n re.lastIndex = 0\n if (re.exec(text) !== null) { return true }\n }\n\n if (this.__opts__.fuzzyEmail && this.__schemas__['mailto:']) {\n // guess schemaless emails\n if (text.indexOf('@') >= 0) {\n // We can't skip this check, because this cases are possible:\n // 192.168.1.1@gmail.com, my.in@example.com\n const mailHostRe = this.re.get_fuzzy_mail_host_search()\n const mailNameRe = this.re.get_mail_name_validator()\n mailHostRe.lastIndex = 0\n\n while ((m = mailHostRe.exec(text)) !== null) {\n const name = text.slice(Math.max(0, m.index - 65), m.index)\n if (mailNameRe.test(name)) { return true }\n }\n }\n }\n\n return false\n }\n\n /**\n * Similar to {@link LinkifyIt.test} but checks only specific protocol tail exactly\n * at given position. Returns length of found pattern (0 on fail).\n *\n * @param text Text to scan.\n * @param schema Rule (schema) name.\n * @param pos Text offset to check from.\n */\n testSchemaAt (text: string, schema: string, pos: number): number {\n // If not supported schema check requested - terminate\n if (!this.__schemas__[schema.toLowerCase()]) { return 0 }\n\n return this.__schemas__[schema.toLowerCase()].validate(\n text.slice(0, pos + this.__opts__.maxLength),\n pos,\n this\n )\n }\n\n /**\n * Returns array of found link descriptions or `null` on fail. We strongly\n * recommend to use {@link LinkifyIt.test} first, for best speed.\n *\n * @param text Text to scan.\n */\n match (text: string): Match[] | null {\n const result: Match[] = []\n const schemaRe = this.re.get_schema_search()\n let fuzzyLinkRe: RegExp | undefined\n let mailHostRe: RegExp | undefined\n let mailNameRe: RegExp | undefined\n let fuzzyLinkCandidate: MatchCandidate | undefined\n let fuzzyEmailCandidate: MatchCandidate | undefined\n let schemaPrefix: MatchCandidate | undefined\n let schemaDone = false\n let fuzzyLinkDone = false\n let fuzzyEmailDone = false\n let pos = 0\n\n if (!text.length) { return null }\n\n schemaRe.lastIndex = 0\n\n if (this.__opts__.fuzzyLink && this.__schemas__['http:']) {\n fuzzyLinkRe = this.re.get_fuzzy_link_search()\n fuzzyLinkRe.lastIndex = 0\n }\n\n if (this.__opts__.fuzzyEmail && this.__schemas__['mailto:']) {\n mailHostRe = this.re.get_fuzzy_mail_host_search()\n mailHostRe.lastIndex = 0\n mailNameRe = this.re.get_mail_name_validator()\n }\n\n for (;;) {\n const scanFrom = Math.max(pos - 1, 0)\n\n if (mailHostRe && mailNameRe && !fuzzyEmailDone && (!fuzzyEmailCandidate || fuzzyEmailCandidate.index < pos)) {\n if (mailHostRe.lastIndex < scanFrom) { mailHostRe.lastIndex = scanFrom }\n\n for (;;) {\n const m = mailHostRe.exec(text)\n if (!m) {\n fuzzyEmailDone = true\n fuzzyEmailCandidate = undefined\n break\n }\n\n const name = mailNameRe.exec(text.slice(Math.max(0, m.index - 65), m.index))\n if (!name) { continue }\n\n fuzzyEmailCandidate = {\n schema: 'mailto:',\n index: m.index - name[1].length,\n lastIndex: m.index + m[0].length\n }\n\n if (fuzzyEmailCandidate.index >= pos) { break }\n if (mailHostRe.lastIndex < scanFrom) { mailHostRe.lastIndex = scanFrom }\n }\n }\n\n if (fuzzyLinkRe && !fuzzyLinkDone && (!fuzzyLinkCandidate || fuzzyLinkCandidate.index < pos)) {\n if (fuzzyLinkRe.lastIndex < scanFrom) { fuzzyLinkRe.lastIndex = scanFrom }\n\n for (;;) {\n const m = fuzzyLinkRe.exec(text)\n if (!m) {\n fuzzyLinkDone = true\n fuzzyLinkCandidate = undefined\n break\n }\n\n fuzzyLinkCandidate = {\n schema: '',\n index: m.index + m[1].length,\n lastIndex: m.index + m[0].length\n }\n\n if (fuzzyLinkCandidate.index >= pos) { break }\n if (fuzzyLinkRe.lastIndex < scanFrom) { fuzzyLinkRe.lastIndex = scanFrom }\n }\n }\n\n let fuzzyCandidate = fuzzyEmailCandidate\n if (!fuzzyCandidate ||\n (fuzzyLinkCandidate &&\n (fuzzyLinkCandidate.index < fuzzyCandidate.index ||\n (fuzzyLinkCandidate.index === fuzzyCandidate.index && fuzzyLinkCandidate.lastIndex > fuzzyCandidate.lastIndex)))) {\n fuzzyCandidate = fuzzyLinkCandidate\n }\n\n let schemaCandidate: MatchCandidate | undefined\n\n if (!schemaDone) {\n for (;;) {\n if (!schemaPrefix) {\n if (schemaRe.lastIndex < scanFrom) { schemaRe.lastIndex = scanFrom }\n\n const m = schemaRe.exec(text)\n if (!m) {\n schemaDone = true\n break\n }\n\n schemaPrefix = {\n schema: m[2],\n index: m.index + m[1].length,\n lastIndex: m.index + m[0].length\n }\n }\n\n if (schemaPrefix.index < pos) {\n schemaPrefix = undefined\n continue\n }\n\n if (fuzzyCandidate && schemaPrefix.index > fuzzyCandidate.index) { break }\n\n const prefix = schemaPrefix\n schemaPrefix = undefined\n\n const len = this.testSchemaAt(text, prefix.schema, prefix.lastIndex)\n if (len) {\n schemaCandidate = {\n schema: prefix.schema,\n index: prefix.index,\n lastIndex: prefix.lastIndex + len\n }\n break\n }\n }\n }\n\n let candidate = schemaCandidate\n if (!candidate ||\n (fuzzyEmailCandidate &&\n (fuzzyEmailCandidate.index < candidate.index ||\n (fuzzyEmailCandidate.index === candidate.index && fuzzyEmailCandidate.lastIndex > candidate.lastIndex)))) {\n candidate = fuzzyEmailCandidate\n }\n if (!candidate ||\n (fuzzyLinkCandidate &&\n (fuzzyLinkCandidate.index < candidate.index ||\n (fuzzyLinkCandidate.index === candidate.index && fuzzyLinkCandidate.lastIndex > candidate.lastIndex)))) {\n candidate = fuzzyLinkCandidate\n }\n\n if (!candidate) { break }\n\n if (candidate === fuzzyEmailCandidate) {\n fuzzyEmailCandidate = undefined\n } else if (candidate === fuzzyLinkCandidate) {\n fuzzyLinkCandidate = undefined\n }\n\n const match = new Match(text, candidate.schema, candidate.index, candidate.lastIndex)\n if (match.schema) {\n this.__schemas__[match.schema].normalize(match, this)\n } else {\n this.normalize(match)\n }\n result.push(match)\n pos = candidate.lastIndex\n }\n\n if (result.length) {\n return result\n }\n\n return null\n }\n\n /**\n * Returns fully-formed (not fuzzy) link if it starts at the beginning\n * of the string, and null otherwise.\n *\n * @param text Text to scan.\n */\n matchAtStart (text: string): Match | null {\n if (!text.length) return null\n\n const m = this.re.get_schema_at_start().exec(text)\n if (!m) return null\n\n const len = this.testSchemaAt(text, m[2], m[0].length)\n if (!len) return null\n\n const match = new Match(text, m[2], m.index + m[1].length, m.index + m[0].length + len)\n\n this.__schemas__[match.schema].normalize(match, this)\n return match\n }\n\n /**\n * Load (or merge) new TLDs list. Those are used for fuzzy links (without\n * prefix) to avoid false positives. By default this algorithm is used:\n *\n * - hostname with any 2-letter root zones are ok.\n * - biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф\n * are ok.\n * - encoded (`xn--...`) root zones are ok.\n *\n * If list is replaced, then exact match for 2-chars root zones will be checked.\n *\n * @param list List of TLDs.\n * @param keepOld Merge with current list if `true` (`false` by default).\n */\n tlds (list: string | string[], keepOld = false): this {\n list = Array.isArray(list) ? list : [list]\n\n if (!keepOld) {\n this.__opts__.tlds = list\n } else {\n this.__opts__.tlds = this.__opts__.tlds.concat(list)\n }\n\n this.re.set({\n ...this.__opts__,\n schema_names: Object.keys(this.__schemas__)\n })\n return this\n }\n\n /**\n * Default normalizer (if schema does not define its own).\n *\n * @param match Match to normalize.\n */\n normalize (match: Match): void {\n // Do minimal possible changes by default. Need to collect feedback prior\n // to move forward https://github.com/markdown-it/linkify-it/issues/1\n\n if (!match.schema) { match.url = `http://${match.url}` }\n\n if (match.schema === 'mailto:' && !/^mailto:/i.test(match.url)) {\n match.url = `mailto:${match.url}`\n }\n }\n}\n\nfunction linkifyit (options: LinkifyConstructorOptions = {}): LinkifyIt {\n return new LinkifyIt(options)\n}\n\nexport { linkifyit }\n"],"mappings":"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"} |
+636
-825
@@ -1,840 +0,651 @@ | ||
| 'use strict'; | ||
| var uc_micro = require('uc.micro'); | ||
| function reFactory (opts) { | ||
| const re = {}; | ||
| opts = opts || {}; | ||
| re.src_Any = uc_micro.Any.source; | ||
| re.src_Cc = uc_micro.Cc.source; | ||
| re.src_Z = uc_micro.Z.source; | ||
| re.src_P = uc_micro.P.source; | ||
| // \p{\Z\P\Cc\CF} (white spaces + control + format + punctuation) | ||
| re.src_ZPCc = [re.src_Z, re.src_P, re.src_Cc].join('|'); | ||
| // \p{\Z\Cc} (white spaces + control) | ||
| re.src_ZCc = [re.src_Z, re.src_Cc].join('|'); | ||
| // Experimental. List of chars, completely prohibited in links | ||
| // because can separate it from other part of text | ||
| const text_separators = '[><\uff5c]'; | ||
| // All possible word characters (everything without punctuation, spaces & controls) | ||
| // Defined via punctuation & spaces to save space | ||
| // Should be something like \p{\L\N\S\M} (\w but without `_`) | ||
| re.src_pseudo_letter = `(?:(?!${text_separators}|${re.src_ZPCc})${re.src_Any})`; | ||
| // The same as abothe but without [0-9] | ||
| // var src_pseudo_letter_non_d = '(?:(?![0-9]|' + src_ZPCc + ')' + src_Any + ')'; | ||
| re.src_ip4 = | ||
| '(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'; | ||
| // Prohibit any of "@/[]()" in user/pass to avoid wrong domain fetch. | ||
| // Length is capped to exclude possible rescans till the end and avoid O(n^2) | ||
| // DoS. No standard limit, just take something reasonable. | ||
| re.src_auth = `(?:(?:(?!${re.src_ZCc}|[@/\\[\\]()]).){1,50}@)?`; | ||
| re.src_port = | ||
| '(?::(?:6(?:[0-4]\\d{3}|5(?:[0-4]\\d{2}|5(?:[0-2]\\d|3[0-5])))|[1-5]?\\d{1,4}))?'; | ||
| re.src_host_terminator = | ||
| `(?=$|${text_separators}|${re.src_ZPCc})` + | ||
| `(?!${opts['---'] ? '-(?!--)|' : '-|'}_|:\\d|\\.-|\\.(?!$|${re.src_ZPCc}))`; | ||
| re.src_path = | ||
| '(?:' + | ||
| '[/?#]' + | ||
| '(?:' + | ||
| `(?!${re.src_ZCc}|${text_separators}|[()[\\]{}.,"'?!\\-;]).|` + | ||
| `\\[(?:(?!${re.src_ZCc}|\\]).)*\\]|` + | ||
| `\\((?:(?!${re.src_ZCc}|[)]).)*\\)|` + | ||
| `\\{(?:(?!${re.src_ZCc}|[}]).)*\\}|` + | ||
| `\\"(?:(?!${re.src_ZCc}|["]).)+\\"|` + | ||
| `\\'(?:(?!${re.src_ZCc}|[']).)+\\'|` + | ||
| // allow `I'm_king` if no pair found | ||
| `\\'(?=${re.src_pseudo_letter}|[-])|` + | ||
| // google has many dots in "google search" links (#66, #81). | ||
| // github has ... in commit range links, | ||
| // Restrict to | ||
| // - english | ||
| // - percent-encoded | ||
| // - parts of file path | ||
| // - params separator | ||
| // until more examples found. | ||
| '\\.{2,}[a-zA-Z0-9%/&]|' + | ||
| `\\.(?!${re.src_ZCc}|[.]|$)|` + | ||
| (opts['---'] | ||
| ? '\\-(?!--(?:[^-]|$))(?:-*)|' // `---` => long dash, terminate | ||
| : '\\-+|' | ||
| ) + | ||
| // allow `,,,` in paths | ||
| `,(?!${re.src_ZCc}|$)|` + | ||
| // allow `;` if not followed by space-like char | ||
| `;(?!${re.src_ZCc}|$)|` + | ||
| // allow `!!!` in paths, but not at the end | ||
| `\\!+(?!${re.src_ZCc}|[!]|$)|` + | ||
| `\\?(?!${re.src_ZCc}|[?]|$)` + | ||
| ')+' + | ||
| '|\\/' + | ||
| ')?'; | ||
| // Allow anything in markdown spec, forbid quote (") at the first position | ||
| // because emails enclosed in quotes are far more common | ||
| // Max name length capped to 64 chars (RFC 5321). This also prevents O(n^2) | ||
| // rescans to the end on inputs like `mailto:mailto:...` | ||
| re.src_email_name = | ||
| '[\\-;:&=\\+\\$,\\.a-zA-Z0-9_][\\-;:&=\\+\\$,\\"\\.a-zA-Z0-9_]{0,63}'; | ||
| re.src_xn = | ||
| 'xn--[a-z0-9\\-]{1,59}'; | ||
| // More to read about domain names | ||
| // http://serverfault.com/questions/638260/ | ||
| re.src_domain_root = | ||
| // Allow letters & digits (http://test1) | ||
| '(?:' + | ||
| re.src_xn + | ||
| '|' + | ||
| `${re.src_pseudo_letter}{1,63}` + | ||
| ')'; | ||
| re.src_domain = | ||
| '(?:' + | ||
| re.src_xn + | ||
| '|' + | ||
| `(?:${re.src_pseudo_letter})` + | ||
| '|' + | ||
| `(?:${re.src_pseudo_letter}(?:-|${re.src_pseudo_letter}){0,61}${re.src_pseudo_letter})` + | ||
| ')'; | ||
| re.src_host = | ||
| '(?:' + | ||
| // Don't need IP check, because digits are already allowed in normal domain names | ||
| // src_ip4 + | ||
| // '|' + | ||
| `(?:(?:(?:${re.src_domain})\\.)*${re.src_domain})`/* _root */ + | ||
| ')'; | ||
| re.tpl_host_fuzzy = | ||
| '(?:' + | ||
| re.src_ip4 + | ||
| '|' + | ||
| `(?:(?:(?:${re.src_domain})\\.)+(?:%TLDS%))` + | ||
| ')'; | ||
| re.tpl_host_no_ip_fuzzy = | ||
| `(?:(?:(?:${re.src_domain})\\.)+(?:%TLDS%))`; | ||
| re.src_host_strict = | ||
| re.src_host + re.src_host_terminator; | ||
| re.tpl_host_fuzzy_strict = | ||
| re.tpl_host_fuzzy + re.src_host_terminator; | ||
| re.src_host_port_strict = | ||
| re.src_host + re.src_port + re.src_host_terminator; | ||
| re.tpl_host_port_fuzzy_strict = | ||
| re.tpl_host_fuzzy + re.src_port + re.src_host_terminator; | ||
| re.tpl_host_port_no_ip_fuzzy_strict = | ||
| re.tpl_host_no_ip_fuzzy + re.src_port + re.src_host_terminator; | ||
| // | ||
| // Main rules | ||
| // | ||
| // Rude test fuzzy links by host, for quick deny | ||
| re.tpl_host_fuzzy_test = | ||
| `localhost|www\\.|\\.\\d{1,3}\\.|(?:\\.(?:%TLDS%)(?:${re.src_ZPCc}|>|$))`; | ||
| re.tpl_email_fuzzy = | ||
| `(^|${text_separators}|"|\\(|${re.src_ZCc})` + | ||
| `(${re.src_email_name}@${re.tpl_host_fuzzy_strict})`; | ||
| re.tpl_link_fuzzy = | ||
| // Fuzzy link can't be prepended with .:/\- and non punctuation. | ||
| // but can start with > (markdown blockquote) | ||
| `(^|(?![.:/\\-_@])(?:[$+<=>^\`|\uff5c]|${re.src_ZPCc}))` + | ||
| `((?![$+<=>^\`|\uff5c])${re.tpl_host_port_fuzzy_strict}${re.src_path})`; | ||
| re.tpl_link_no_ip_fuzzy = | ||
| // Fuzzy link can't be prepended with .:/\- and non punctuation. | ||
| // but can start with > (markdown blockquote) | ||
| `(^|(?![.:/\\-_@])(?:[$+<=>^\`|\uff5c]|${re.src_ZPCc}))` + | ||
| `((?![$+<=>^\`|\uff5c])${re.tpl_host_port_no_ip_fuzzy_strict}${re.src_path})`; | ||
| return re | ||
| Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); | ||
| let uc_micro = require("uc.micro"); | ||
| //#region \0@oxc-project+runtime@0.138.0/helpers/esm/typeof.js | ||
| function _typeof(o) { | ||
| "@babel/helpers - typeof"; | ||
| return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) { | ||
| return typeof o; | ||
| } : function(o) { | ||
| return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; | ||
| }, _typeof(o); | ||
| } | ||
| // | ||
| // Helpers | ||
| // | ||
| // Merge objects | ||
| // | ||
| function assign (obj /* from1, from2, from3, ... */) { | ||
| const sources = Array.prototype.slice.call(arguments, 1); | ||
| sources.forEach(function (source) { | ||
| if (!source) { return } | ||
| Object.keys(source).forEach(function (key) { | ||
| obj[key] = source[key]; | ||
| }); | ||
| }); | ||
| return obj | ||
| //#endregion | ||
| //#region \0@oxc-project+runtime@0.138.0/helpers/esm/toPrimitive.js | ||
| function toPrimitive(t, r) { | ||
| if ("object" != _typeof(t) || !t) return t; | ||
| var e = t[Symbol.toPrimitive]; | ||
| if (void 0 !== e) { | ||
| var i = e.call(t, r || "default"); | ||
| if ("object" != _typeof(i)) return i; | ||
| throw new TypeError("@@toPrimitive must return a primitive value."); | ||
| } | ||
| return ("string" === r ? String : Number)(t); | ||
| } | ||
| function _class (obj) { return Object.prototype.toString.call(obj) } | ||
| function isString (obj) { return _class(obj) === '[object String]' } | ||
| function isObject (obj) { return _class(obj) === '[object Object]' } | ||
| function isRegExp (obj) { return _class(obj) === '[object RegExp]' } | ||
| function isFunction (obj) { return _class(obj) === '[object Function]' } | ||
| function escapeRE (str) { return str.replace(/[.?*+^$[\]\\(){}|-]/g, '\\$&') } | ||
| // | ||
| const defaultOptions = { | ||
| fuzzyLink: true, | ||
| fuzzyEmail: true, | ||
| fuzzyIP: false | ||
| }; | ||
| function isOptionsObj (obj) { | ||
| return Object.keys(obj || {}).reduce(function (acc, k) { | ||
| /* eslint-disable-next-line no-prototype-builtins */ | ||
| return acc || defaultOptions.hasOwnProperty(k) | ||
| }, false) | ||
| //#endregion | ||
| //#region \0@oxc-project+runtime@0.138.0/helpers/esm/toPropertyKey.js | ||
| function toPropertyKey(t) { | ||
| var i = toPrimitive(t, "string"); | ||
| return "symbol" == _typeof(i) ? i : i + ""; | ||
| } | ||
| const defaultSchemas = { | ||
| 'http:': { | ||
| validate: function (text, pos, self) { | ||
| const tail = text.slice(pos); | ||
| if (!self.re.http) { | ||
| // compile lazily, because "host"-containing variables can change on tlds update. | ||
| self.re.http = new RegExp( | ||
| `^\\/\\/${self.re.src_auth}${self.re.src_host_port_strict}${self.re.src_path}`, 'i' | ||
| ); | ||
| } | ||
| if (self.re.http.test(tail)) { | ||
| return tail.match(self.re.http)[0].length | ||
| } | ||
| return 0 | ||
| } | ||
| }, | ||
| 'https:': 'http:', | ||
| 'ftp:': 'http:', | ||
| '//': { | ||
| validate: function (text, pos, self) { | ||
| const tail = text.slice(pos); | ||
| if (!self.re.no_http) { | ||
| // compile lazily, because "host"-containing variables can change on tlds update. | ||
| self.re.no_http = new RegExp( | ||
| '^' + | ||
| self.re.src_auth + | ||
| // Don't allow single-level domains, because of false positives like '//test' | ||
| // with code comments | ||
| `(?:localhost|(?:(?:${self.re.src_domain})\\.)+${self.re.src_domain_root})` + | ||
| self.re.src_port + | ||
| self.re.src_host_terminator + | ||
| self.re.src_path, | ||
| 'i' | ||
| ); | ||
| } | ||
| if (self.re.no_http.test(tail)) { | ||
| // should not be `://` & `///`, that protects from errors in protocol name | ||
| if (pos >= 3 && text[pos - 3] === ':') { return 0 } | ||
| if (pos >= 3 && text[pos - 3] === '/') { return 0 } | ||
| return tail.match(self.re.no_http)[0].length | ||
| } | ||
| return 0 | ||
| } | ||
| }, | ||
| 'mailto:': { | ||
| validate: function (text, pos, self) { | ||
| const tail = text.slice(pos); | ||
| if (!self.re.mailto) { | ||
| self.re.mailto = new RegExp( | ||
| `^${self.re.src_email_name}@${self.re.src_host_strict}`, 'i' | ||
| ); | ||
| } | ||
| if (self.re.mailto.test(tail)) { | ||
| return tail.match(self.re.mailto)[0].length | ||
| } | ||
| return 0 | ||
| } | ||
| } | ||
| }; | ||
| // RE pattern for 2-character tlds (autogenerated by ./support/tlds_2char_gen.js) | ||
| const tlds_2ch_src_re = '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]|om|p[aefghklmnrstwy]|qa|r[eosuw]|s[abcdeghijklmnortuvxyz]|t[cdfghjklmnortvwz]|u[agksyz]|v[aceginu]|w[fs]|y[et]|z[amw]'; | ||
| // DON'T try to make PRs with changes. Extend TLDs with LinkifyIt.tlds() instead | ||
| const tlds_default = 'biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф'.split('|'); | ||
| function createValidator (re) { | ||
| return function (text, pos) { | ||
| const tail = text.slice(pos); | ||
| if (re.test(tail)) { | ||
| return tail.match(re)[0].length | ||
| } | ||
| return 0 | ||
| } | ||
| //#endregion | ||
| //#region \0@oxc-project+runtime@0.138.0/helpers/esm/defineProperty.js | ||
| function _defineProperty(e, r, t) { | ||
| return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, { | ||
| value: t, | ||
| enumerable: !0, | ||
| configurable: !0, | ||
| writable: !0 | ||
| }) : e[r] = t, e; | ||
| } | ||
| function createNormalizer () { | ||
| return function (match, self) { | ||
| self.normalize(match); | ||
| } | ||
| //#endregion | ||
| //#region \0@oxc-project+runtime@0.138.0/helpers/esm/objectSpread2.js | ||
| function ownKeys(e, r) { | ||
| var t = Object.keys(e); | ||
| if (Object.getOwnPropertySymbols) { | ||
| var o = Object.getOwnPropertySymbols(e); | ||
| r && (o = o.filter(function(r) { | ||
| return Object.getOwnPropertyDescriptor(e, r).enumerable; | ||
| })), t.push.apply(t, o); | ||
| } | ||
| return t; | ||
| } | ||
| // Schemas compiler. Build regexps. | ||
| // | ||
| function compile (self) { | ||
| // Load & clone RE patterns. | ||
| const re = self.re = reFactory(self.__opts__); | ||
| // Define dynamic patterns | ||
| const tlds = self.__tlds__.slice(); | ||
| self.onCompile(); | ||
| if (!self.__tlds_replaced__) { | ||
| tlds.push(tlds_2ch_src_re); | ||
| } | ||
| tlds.push(re.src_xn); | ||
| re.src_tlds = tlds.join('|'); | ||
| function untpl (tpl) { return tpl.replace('%TLDS%', re.src_tlds) } | ||
| re.email_fuzzy = RegExp(untpl(re.tpl_email_fuzzy), 'i'); | ||
| re.email_fuzzy_global = RegExp(untpl(re.tpl_email_fuzzy), 'ig'); | ||
| re.link_fuzzy = RegExp(untpl(re.tpl_link_fuzzy), 'i'); | ||
| re.link_fuzzy_global = RegExp(untpl(re.tpl_link_fuzzy), 'ig'); | ||
| re.link_no_ip_fuzzy = RegExp(untpl(re.tpl_link_no_ip_fuzzy), 'i'); | ||
| re.link_no_ip_fuzzy_global = RegExp(untpl(re.tpl_link_no_ip_fuzzy), 'ig'); | ||
| re.host_fuzzy_test = RegExp(untpl(re.tpl_host_fuzzy_test), 'i'); | ||
| // | ||
| // Compile each schema | ||
| // | ||
| const aliases = []; | ||
| self.__compiled__ = {}; // Reset compiled data | ||
| function schemaError (name, val) { | ||
| throw new Error(`(LinkifyIt) Invalid schema "${name}": ${val}`) | ||
| } | ||
| Object.keys(self.__schemas__).forEach(function (name) { | ||
| const val = self.__schemas__[name]; | ||
| // skip disabled methods | ||
| if (val === null) { return } | ||
| const compiled = { validate: null, link: null }; | ||
| self.__compiled__[name] = compiled; | ||
| if (isObject(val)) { | ||
| if (isRegExp(val.validate)) { | ||
| compiled.validate = createValidator(val.validate); | ||
| } else if (isFunction(val.validate)) { | ||
| compiled.validate = val.validate; | ||
| } else { | ||
| schemaError(name, val); | ||
| } | ||
| if (isFunction(val.normalize)) { | ||
| compiled.normalize = val.normalize; | ||
| } else if (!val.normalize) { | ||
| compiled.normalize = createNormalizer(); | ||
| } else { | ||
| schemaError(name, val); | ||
| } | ||
| return | ||
| } | ||
| if (isString(val)) { | ||
| aliases.push(name); | ||
| return | ||
| } | ||
| schemaError(name, val); | ||
| }); | ||
| // | ||
| // Compile postponed aliases | ||
| // | ||
| aliases.forEach(function (alias) { | ||
| if (!self.__compiled__[self.__schemas__[alias]]) { | ||
| // Silently fail on missed schemas to avoid errons on disable. | ||
| // schemaError(alias, self.__schemas__[alias]); | ||
| return | ||
| } | ||
| self.__compiled__[alias].validate = | ||
| self.__compiled__[self.__schemas__[alias]].validate; | ||
| self.__compiled__[alias].normalize = | ||
| self.__compiled__[self.__schemas__[alias]].normalize; | ||
| }); | ||
| // | ||
| // Fake record for guessed links | ||
| // | ||
| self.__compiled__[''] = { validate: null, normalize: createNormalizer() }; | ||
| // | ||
| // Build schema condition | ||
| // | ||
| const slist = Object.keys(self.__compiled__) | ||
| .filter(function (name) { | ||
| // Filter disabled & fake schemas | ||
| return name.length > 0 && self.__compiled__[name] | ||
| }) | ||
| .map(escapeRE) | ||
| .join('|'); | ||
| // (?!_) cause 1.5x slowdown | ||
| self.re.schema_test = RegExp(`(^|(?!_)(?:[><\uff5c]|${re.src_ZPCc}))(${slist})`, 'i'); | ||
| self.re.schema_search = RegExp(`(^|(?!_)(?:[><\uff5c]|${re.src_ZPCc}))(${slist})`, 'ig'); | ||
| self.re.schema_at_start = RegExp(`^${self.re.schema_search.source}`, 'i'); | ||
| self.re.pretest = RegExp( | ||
| `(${self.re.schema_test.source})|(${self.re.host_fuzzy_test.source})|@`, | ||
| 'i' | ||
| ); | ||
| function _objectSpread2(e) { | ||
| for (var r = 1; r < arguments.length; r++) { | ||
| var t = null != arguments[r] ? arguments[r] : {}; | ||
| r % 2 ? ownKeys(Object(t), !0).forEach(function(r) { | ||
| _defineProperty(e, r, t[r]); | ||
| }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r) { | ||
| Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); | ||
| }); | ||
| } | ||
| return e; | ||
| } | ||
| /** | ||
| * class Match | ||
| * | ||
| * Match result. Single element of array, returned by [[LinkifyIt#match]] | ||
| **/ | ||
| function Match (text, schema, index, lastIndex) { | ||
| const raw = text.slice(index, lastIndex); | ||
| /** | ||
| * Match#schema -> String | ||
| * | ||
| * Prefix (protocol) for matched string. | ||
| **/ | ||
| this.schema = schema.toLowerCase(); | ||
| /** | ||
| * Match#index -> Number | ||
| * | ||
| * First position of matched string. | ||
| **/ | ||
| this.index = index; | ||
| /** | ||
| * Match#lastIndex -> Number | ||
| * | ||
| * Next position after matched string. | ||
| **/ | ||
| this.lastIndex = lastIndex; | ||
| /** | ||
| * Match#raw -> String | ||
| * | ||
| * Matched string. | ||
| **/ | ||
| this.raw = raw; | ||
| /** | ||
| * Match#text -> String | ||
| * | ||
| * Notmalized text of matched string. | ||
| **/ | ||
| this.text = raw; | ||
| /** | ||
| * Match#url -> String | ||
| * | ||
| * Normalized url of matched string. | ||
| **/ | ||
| this.url = raw; | ||
| //#endregion | ||
| //#region src/rebuilder.ts | ||
| var REBuilder = class { | ||
| constructor(opts = {}) { | ||
| _defineProperty(this, "src_Any", uc_micro.Any.source); | ||
| _defineProperty(this, "src_Cc", uc_micro.Cc.source); | ||
| _defineProperty(this, "src_Z", uc_micro.Z.source); | ||
| _defineProperty(this, "src_P", uc_micro.P.source); | ||
| _defineProperty(this, "src_ZPCc", [ | ||
| this.src_Z, | ||
| this.src_P, | ||
| this.src_Cc | ||
| ].join("|")); | ||
| _defineProperty(this, "src_ZCc", [this.src_Z, this.src_Cc].join("|")); | ||
| _defineProperty(this, "cache", {}); | ||
| _defineProperty(this, "opts", { | ||
| maxLength: 1e4, | ||
| urlAuth: false, | ||
| schema_names: [] | ||
| }); | ||
| this.opts = _objectSpread2(_objectSpread2({}, this.opts), opts); | ||
| } | ||
| set(opts = {}) { | ||
| this.opts = _objectSpread2(_objectSpread2({}, 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() { | ||
| var _this$cache, _this$cache$text_sepa; | ||
| return (_this$cache$text_sepa = (_this$cache = this.cache).text_separators) !== null && _this$cache$text_sepa !== void 0 ? _this$cache$text_sepa : _this$cache.text_separators = /[><\uff5c]/; | ||
| } | ||
| get_pseudo_letter() { | ||
| var _this$cache2, _this$cache2$src_pseu; | ||
| return (_this$cache2$src_pseu = (_this$cache2 = this.cache).src_pseudo_letter) !== null && _this$cache2$src_pseu !== void 0 ? _this$cache2$src_pseu : _this$cache2.src_pseudo_letter = new RegExp(`(?:(?!${this.get_text_separators().source}|${this.src_ZPCc})${this.src_Any})`); | ||
| } | ||
| get_ipv4_addr() { | ||
| var _this$cache3, _this$cache3$src_ip; | ||
| return (_this$cache3$src_ip = (_this$cache3 = this.cache).src_ip4) !== null && _this$cache3$src_ip !== void 0 ? _this$cache3$src_ip : _this$cache3.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() { | ||
| var _this$cache4, _this$cache4$src_ip6_; | ||
| const h16 = "[0-9A-Fa-f]{1,4}"; | ||
| const ls32 = `(?:(?:${h16}:${h16})|${this.get_ipv4_addr().source})`; | ||
| return (_this$cache4$src_ip6_ = (_this$cache4 = this.cache).src_ip6_addr) !== null && _this$cache4$src_ip6_ !== void 0 ? _this$cache4$src_ip6_ : _this$cache4.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() { | ||
| var _this$cache5, _this$cache5$src_ip6_; | ||
| return (_this$cache5$src_ip6_ = (_this$cache5 = this.cache).src_ip6_host) !== null && _this$cache5$src_ip6_ !== void 0 ? _this$cache5$src_ip6_ : _this$cache5.src_ip6_host = new RegExp(`\\[${this.get_ipv6_addr().source}\\]`); | ||
| } | ||
| get_ipv6_mail_host() { | ||
| var _this$cache6, _this$cache6$src_ipv; | ||
| return (_this$cache6$src_ipv = (_this$cache6 = this.cache).src_ipv6_mail_host) !== null && _this$cache6$src_ipv !== void 0 ? _this$cache6$src_ipv : _this$cache6.src_ipv6_mail_host = new RegExp(`\\[IPv6:${this.get_ipv6_addr().source}\\]`); | ||
| } | ||
| get_auth() { | ||
| var _this$cache7, _this$cache7$src_auth; | ||
| return (_this$cache7$src_auth = (_this$cache7 = this.cache).src_auth) !== null && _this$cache7$src_auth !== void 0 ? _this$cache7$src_auth : _this$cache7.src_auth = new RegExp(`(?:(?:(?!${this.src_ZCc}|[@/\\[\\]()]).){1,50}@)?`); | ||
| } | ||
| get_port() { | ||
| var _this$cache8, _this$cache8$src_port; | ||
| return (_this$cache8$src_port = (_this$cache8 = this.cache).src_port) !== null && _this$cache8$src_port !== void 0 ? _this$cache8$src_port : _this$cache8.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() { | ||
| var _this$cache9, _this$cache9$src_host; | ||
| return (_this$cache9$src_host = (_this$cache9 = this.cache).src_host_terminator) !== null && _this$cache9$src_host !== void 0 ? _this$cache9$src_host : _this$cache9.src_host_terminator = new RegExp(`(?=$|${this.get_text_separators().source}|${this.src_ZPCc})(?!${this.opts["---"] ? "-(?!--)|" : "-|"}_|:\\d|\\.-|\\.(?!$|${this.src_ZPCc}))`); | ||
| } | ||
| get_path_terminator() { | ||
| var _this$cache10, _this$cache10$src_pat; | ||
| return (_this$cache10$src_pat = (_this$cache10 = this.cache).src_path_terminator) !== null && _this$cache10$src_pat !== void 0 ? _this$cache10$src_pat : _this$cache10.src_path_terminator = new RegExp(`${this.src_ZPCc}|${this.get_text_separators().source}`); | ||
| } | ||
| get_path() { | ||
| var _this$cache11, _this$cache11$src_pat; | ||
| return (_this$cache11$src_pat = (_this$cache11 = this.cache).src_path) !== null && _this$cache11$src_pat !== void 0 ? _this$cache11$src_pat : _this$cache11.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() { | ||
| var _this$cache12, _this$cache12$src_mai; | ||
| return (_this$cache12$src_mai = (_this$cache12 = this.cache).src_mail_name) !== null && _this$cache12$src_mai !== void 0 ? _this$cache12$src_mai : _this$cache12.src_mail_name = /* @__PURE__ */ new RegExp("[-!#$%&'*+/=?^_`{|}~a-zA-Z0-9](?:[-!#$%&'*+/=?^_`{|}~a-zA-Z0-9]|[.](?=[-!#$%&'*+/=?^_`{|}~a-zA-Z0-9])){0,63}"); | ||
| } | ||
| get_xn() { | ||
| var _this$cache13, _this$cache13$src_xn; | ||
| return (_this$cache13$src_xn = (_this$cache13 = this.cache).src_xn) !== null && _this$cache13$src_xn !== void 0 ? _this$cache13$src_xn : _this$cache13.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() { | ||
| var _this$cache14, _this$cache14$src_dom; | ||
| return (_this$cache14$src_dom = (_this$cache14 = this.cache).src_domain_root) !== null && _this$cache14$src_dom !== void 0 ? _this$cache14$src_dom : _this$cache14.src_domain_root = new RegExp("(?:" + this.get_xn().source + `|${this.get_pseudo_letter().source}{1,63})`); | ||
| } | ||
| get_domain() { | ||
| var _this$cache15, _this$cache15$src_dom; | ||
| return (_this$cache15$src_dom = (_this$cache15 = this.cache).src_domain) !== null && _this$cache15$src_dom !== void 0 ? _this$cache15$src_dom : _this$cache15.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() { | ||
| var _this$cache16, _this$cache16$url_hos; | ||
| return (_this$cache16$url_hos = (_this$cache16 = this.cache).url_host_port) !== null && _this$cache16$url_hos !== void 0 ? _this$cache16$url_hos : _this$cache16.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() { | ||
| var _this$cache17, _this$cache17$fuzzy_u; | ||
| return (_this$cache17$fuzzy_u = (_this$cache17 = this.cache).fuzzy_url_host_port) !== null && _this$cache17$fuzzy_u !== void 0 ? _this$cache17$fuzzy_u : _this$cache17.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() { | ||
| var _this$cache18, _this$cache18$src_mai; | ||
| return (_this$cache18$src_mai = (_this$cache18 = this.cache).src_mail_host) !== null && _this$cache18$src_mai !== void 0 ? _this$cache18$src_mai : _this$cache18.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() { | ||
| var _this$cache19, _this$cache19$src_fuz; | ||
| return (_this$cache19$src_fuz = (_this$cache19 = this.cache).src_fuzzy_mail_host) !== null && _this$cache19$src_fuz !== void 0 ? _this$cache19$src_fuz : _this$cache19.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() { | ||
| var _this$cache20, _this$cache20$src_pat; | ||
| return (_this$cache20$src_pat = (_this$cache20 = this.cache).src_path_extra) !== null && _this$cache20$src_pat !== void 0 ? _this$cache20$src_pat : _this$cache20.src_path_extra = /* @__PURE__ */ new RegExp(""); | ||
| } | ||
| get_fuzzy_mail_host_search() { | ||
| var _this$cache21, _this$cache21$mail_fu; | ||
| return (_this$cache21$mail_fu = (_this$cache21 = this.cache).mail_fuzzy_host_search) !== null && _this$cache21$mail_fu !== void 0 ? _this$cache21$mail_fu : _this$cache21.mail_fuzzy_host_search = new RegExp(`@${this.get_fuzzy_mail_host().source}`, "ig"); | ||
| } | ||
| get_fuzzy_link_search() { | ||
| var _this$cache22, _this$cache22$link_fu; | ||
| return (_this$cache22$link_fu = (_this$cache22 = this.cache).link_fuzzy_search) !== null && _this$cache22$link_fu !== void 0 ? _this$cache22$link_fu : _this$cache22.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() { | ||
| var _this$cache23, _this$cache23$http_va; | ||
| return (_this$cache23$http_va = (_this$cache23 = this.cache).http_validator) !== null && _this$cache23$http_va !== void 0 ? _this$cache23$http_va : _this$cache23.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() { | ||
| var _this$cache24, _this$cache24$relativ; | ||
| return (_this$cache24$relativ = (_this$cache24 = this.cache).relative_proto_validator) !== null && _this$cache24$relativ !== void 0 ? _this$cache24$relativ : _this$cache24.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() { | ||
| var _this$cache25, _this$cache25$mail_na; | ||
| return (_this$cache25$mail_na = (_this$cache25 = this.cache).mail_name_validator) !== null && _this$cache25$mail_na !== void 0 ? _this$cache25$mail_na : _this$cache25.mail_name_validator = new RegExp(`(?:^|${this.get_text_separators().source}|"|\\(|${this.src_ZCc})(${this.get_mail_name().source})$`); | ||
| } | ||
| get_mailto_validator() { | ||
| var _this$cache26, _this$cache26$mailto_; | ||
| return (_this$cache26$mailto_ = (_this$cache26 = this.cache).mailto_validator) !== null && _this$cache26$mailto_ !== void 0 ? _this$cache26$mailto_ : _this$cache26.mailto_validator = new RegExp(`${this.get_mail_name().source}@${this.get_mail_host().source}`, "iy"); | ||
| } | ||
| get_schema_names() { | ||
| var _this$cache27, _this$cache27$schema_; | ||
| return (_this$cache27$schema_ = (_this$cache27 = this.cache).schema_names) !== null && _this$cache27$schema_ !== void 0 ? _this$cache27$schema_ : _this$cache27.schema_names = new RegExp((this.opts.schema_names || []).map((name) => this.escapeRE(name)).join("|")); | ||
| } | ||
| get_schema_search() { | ||
| var _this$cache28, _this$cache28$schema_; | ||
| return (_this$cache28$schema_ = (_this$cache28 = this.cache).schema_search) !== null && _this$cache28$schema_ !== void 0 ? _this$cache28$schema_ : _this$cache28.schema_search = new RegExp(`(^|(?!_)(?:[><\uff5c]|${this.src_ZPCc}))(${this.get_schema_names().source})`, "ig"); | ||
| } | ||
| get_schema_at_start() { | ||
| var _this$cache29, _this$cache29$schema_; | ||
| return (_this$cache29$schema_ = (_this$cache29 = this.cache).schema_at_start) !== null && _this$cache29$schema_ !== void 0 ? _this$cache29$schema_ : _this$cache29.schema_at_start = new RegExp(`^${this.get_schema_search().source}`, "i"); | ||
| } | ||
| }; | ||
| //#endregion | ||
| //#region \0@oxc-project+runtime@0.138.0/helpers/esm/objectWithoutPropertiesLoose.js | ||
| function _objectWithoutPropertiesLoose(r, e) { | ||
| if (null == r) return {}; | ||
| var t = {}; | ||
| for (var n in r) if ({}.hasOwnProperty.call(r, n)) { | ||
| if (e.includes(n)) continue; | ||
| t[n] = r[n]; | ||
| } | ||
| return t; | ||
| } | ||
| /** | ||
| * class LinkifyIt | ||
| **/ | ||
| /** | ||
| * new LinkifyIt(schemas, options) | ||
| * - schemas (Object): Optional. Additional schemas to validate (prefix/validator) | ||
| * - options (Object): { fuzzyLink|fuzzyEmail|fuzzyIP: true|false } | ||
| * | ||
| * Creates new linkifier instance with optional additional schemas. | ||
| * Can be called without `new` keyword for convenience. | ||
| * | ||
| * By default understands: | ||
| * | ||
| * - `http(s)://...` , `ftp://...`, `mailto:...` & `//...` links | ||
| * - "fuzzy" links and emails (example.com, foo@bar.com). | ||
| * | ||
| * `schemas` is an object, where each key/value describes protocol/rule: | ||
| * | ||
| * - __key__ - link prefix (usually, protocol name with `:` at the end, `skype:` | ||
| * for example). `linkify-it` makes shure that prefix is not preceeded with | ||
| * alphanumeric char and symbols. Only whitespaces and punctuation allowed. | ||
| * - __value__ - rule to check tail after link prefix | ||
| * - _String_ - just alias to existing rule | ||
| * - _Object_ | ||
| * - _validate_ - validator function (should return matched length on success), | ||
| * or `RegExp`. | ||
| * - _normalize_ - optional function to normalize text & url of matched result | ||
| * (for example, for @twitter mentions). | ||
| * | ||
| * `options`: | ||
| * | ||
| * - __fuzzyLink__ - recognige URL-s without `http(s):` prefix. Default `true`. | ||
| * - __fuzzyIP__ - allow IPs in fuzzy links above. Can conflict with some texts | ||
| * like version numbers. Default `false`. | ||
| * - __fuzzyEmail__ - recognize emails without `mailto:` prefix. | ||
| * | ||
| **/ | ||
| function LinkifyIt (schemas, options) { | ||
| if (!(this instanceof LinkifyIt)) { | ||
| return new LinkifyIt(schemas, options) | ||
| } | ||
| if (!options) { | ||
| if (isOptionsObj(schemas)) { | ||
| options = schemas; | ||
| schemas = {}; | ||
| } | ||
| } | ||
| this.__opts__ = assign({}, defaultOptions, options); | ||
| this.__schemas__ = assign({}, defaultSchemas, schemas); | ||
| this.__compiled__ = {}; | ||
| this.__tlds__ = tlds_default; | ||
| this.__tlds_replaced__ = false; | ||
| this.re = {}; | ||
| compile(this); | ||
| //#endregion | ||
| //#region \0@oxc-project+runtime@0.138.0/helpers/esm/objectWithoutProperties.js | ||
| function _objectWithoutProperties(e, t) { | ||
| if (null == e) return {}; | ||
| var o, r, i = _objectWithoutPropertiesLoose(e, t); | ||
| if (Object.getOwnPropertySymbols) { | ||
| var s = Object.getOwnPropertySymbols(e); | ||
| for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); | ||
| } | ||
| return i; | ||
| } | ||
| /** chainable | ||
| * LinkifyIt#add(schema, definition) | ||
| * - schema (String): rule name (fixed pattern prefix) | ||
| * - definition (String|RegExp|Object): schema definition | ||
| * | ||
| * Add new rule definition. See constructor description for details. | ||
| **/ | ||
| LinkifyIt.prototype.add = function add (schema, definition) { | ||
| this.__schemas__[schema] = definition; | ||
| compile(this); | ||
| return this | ||
| //#endregion | ||
| //#region src/linkifyit.ts | ||
| var _excluded = ["rebuilder"]; | ||
| 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) | ||
| }; | ||
| /** chainable | ||
| * LinkifyIt#set(options) | ||
| * - options (Object): { fuzzyLink|fuzzyEmail|fuzzyIP: true|false } | ||
| * | ||
| * Set recognition options for links without schema. | ||
| **/ | ||
| LinkifyIt.prototype.set = function set (options) { | ||
| this.__opts__ = assign(this.__opts__, options); | ||
| return this | ||
| 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) | ||
| } | ||
| }; | ||
| /** | ||
| * LinkifyIt#test(text) -> Boolean | ||
| * | ||
| * Searches linkifiable pattern and returns `true` on success or `false` on fail. | ||
| **/ | ||
| LinkifyIt.prototype.test = function test (text) { | ||
| if (!text.length) { return false } | ||
| let m, re; | ||
| // try to scan for link with schema - that's the most simple rule | ||
| if (this.re.schema_test.test(text)) { | ||
| re = this.re.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.__compiled__['http:']) { | ||
| // guess schemaless links | ||
| if (text.search(this.re.host_fuzzy_test) >= 0) { | ||
| if (text.match(this.__opts__.fuzzyIP ? this.re.link_fuzzy : this.re.link_no_ip_fuzzy) !== null) { | ||
| return true | ||
| } | ||
| } | ||
| } | ||
| if (this.__opts__.fuzzyEmail && this.__compiled__['mailto:']) { | ||
| // guess schemaless emails | ||
| if (text.indexOf('@') >= 0) { | ||
| // We can't skip this check, because this cases are possible: | ||
| // 192.168.1.1@gmail.com, my.in@example.com | ||
| if (text.match(this.re.email_fuzzy) !== null) { return true } | ||
| } | ||
| } | ||
| return false | ||
| 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 | ||
| }; | ||
| /** | ||
| * LinkifyIt#pretest(text) -> Boolean | ||
| * | ||
| * Very quick check, that can give false positives. Returns true if link MAY BE | ||
| * can exists. Can be used for speed optimization, when you need to check that | ||
| * link NOT exists. | ||
| **/ | ||
| LinkifyIt.prototype.pretest = function pretest (text) { | ||
| return this.re.pretest.test(text) | ||
| * Match result returned by {@link LinkifyIt.match} and | ||
| * {@link LinkifyIt.matchAtStart}. | ||
| * | ||
| * @category types | ||
| */ | ||
| var Match = class { | ||
| constructor(text, schema, index, lastIndex) { | ||
| _defineProperty( | ||
| this, | ||
| /** Prefix (protocol) for matched string. Empty for fuzzy links. */ | ||
| "schema", | ||
| void 0 | ||
| ); | ||
| _defineProperty( | ||
| this, | ||
| /** First position of matched string. */ | ||
| "index", | ||
| void 0 | ||
| ); | ||
| _defineProperty( | ||
| this, | ||
| /** Next position after matched string. */ | ||
| "lastIndex", | ||
| void 0 | ||
| ); | ||
| _defineProperty( | ||
| this, | ||
| /** Matched string. */ | ||
| "raw", | ||
| void 0 | ||
| ); | ||
| _defineProperty( | ||
| this, | ||
| /** Normalized text of matched string. */ | ||
| "text", | ||
| void 0 | ||
| ); | ||
| _defineProperty( | ||
| this, | ||
| /** Normalized URL of matched string. */ | ||
| "url", | ||
| void 0 | ||
| ); | ||
| 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; | ||
| } | ||
| }; | ||
| /** | ||
| * LinkifyIt#testSchemaAt(text, name, position) -> Number | ||
| * - text (String): text to scan | ||
| * - name (String): rule (schema) name | ||
| * - position (Number): text offset to check from | ||
| * | ||
| * Similar to [[LinkifyIt#test]] but checks only specific protocol tail exactly | ||
| * at given position. Returns length of found pattern (0 on fail). | ||
| **/ | ||
| LinkifyIt.prototype.testSchemaAt = function testSchemaAt (text, schema, pos) { | ||
| // If not supported schema check requested - terminate | ||
| if (!this.__compiled__[schema.toLowerCase()]) { | ||
| return 0 | ||
| } | ||
| return this.__compiled__[schema.toLowerCase()].validate(text, pos, this) | ||
| /** Linkifier instance. */ | ||
| var LinkifyIt = class { | ||
| /** | ||
| * 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 = {}) { | ||
| _defineProperty(this, "__opts__", void 0); | ||
| _defineProperty(this, "__schemas__", void 0); | ||
| _defineProperty(this, "re", void 0); | ||
| const { rebuilder } = options, linkifyOptions = _objectWithoutProperties(options, _excluded); | ||
| this.__opts__ = _objectSpread2(_objectSpread2({}, defaultOptions), linkifyOptions); | ||
| this.__schemas__ = _objectSpread2({}, defaultSchemas); | ||
| this.re = rebuilder || new REBuilder(); | ||
| this.re.set(_objectSpread2(_objectSpread2({}, 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 = _objectSpread2({ normalize: (match, self) => self.normalize(match) }, definition); | ||
| this.__schemas__[schema] = def; | ||
| } | ||
| this.re.set(_objectSpread2(_objectSpread2({}, 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__ = _objectSpread2(_objectSpread2({}, this.__opts__), options); | ||
| this.re.set(_objectSpread2(_objectSpread2({}, 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(_objectSpread2(_objectSpread2({}, 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}`; | ||
| } | ||
| }; | ||
| function linkifyit(options = {}) { | ||
| return new LinkifyIt(options); | ||
| } | ||
| //#endregion | ||
| exports.LinkifyIt = LinkifyIt; | ||
| exports.REBuilder = REBuilder; | ||
| exports.linkifyit = linkifyit; | ||
| /** | ||
| * LinkifyIt#match(text) -> Array|null | ||
| * | ||
| * Returns array of found link descriptions or `null` on fail. We strongly | ||
| * recommend to use [[LinkifyIt#test]] first, for best speed. | ||
| * | ||
| * ##### Result match description | ||
| * | ||
| * - __schema__ - link schema, can be empty for fuzzy links, or `//` for | ||
| * protocol-neutral links. | ||
| * - __index__ - offset of matched text | ||
| * - __lastIndex__ - index of next char after mathch end | ||
| * - __raw__ - matched text | ||
| * - __text__ - normalized text | ||
| * - __url__ - link, generated from matched text | ||
| **/ | ||
| LinkifyIt.prototype.match = function match (text) { | ||
| const result = []; | ||
| const type_schemed = []; | ||
| const type_fuzzy_link = []; | ||
| const type_fuzzy_email = []; | ||
| let m, len, re; | ||
| function choose (a, b) { | ||
| if (!a) { return b } | ||
| if (!b) { return a } | ||
| if (a.index !== b.index) { return a.index < b.index ? a : b } | ||
| return a.lastIndex >= b.lastIndex ? a : b | ||
| } | ||
| if (!text.length) { return null } | ||
| // scan for links with schema | ||
| if (this.re.schema_test.test(text)) { | ||
| re = this.re.schema_search; | ||
| re.lastIndex = 0; | ||
| while ((m = re.exec(text)) !== null) { | ||
| len = this.testSchemaAt(text, m[2], re.lastIndex); | ||
| if (len) { | ||
| type_schemed.push({ | ||
| schema: m[2], | ||
| index: m.index + m[1].length, | ||
| lastIndex: m.index + m[0].length + len | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| if (this.__opts__.fuzzyLink && this.__compiled__['http:']) { | ||
| re = this.__opts__.fuzzyIP ? this.re.link_fuzzy_global : this.re.link_no_ip_fuzzy_global; | ||
| re.lastIndex = 0; | ||
| while ((m = re.exec(text)) !== null) { | ||
| type_fuzzy_link.push({ | ||
| schema: '', | ||
| index: m.index + m[1].length, | ||
| lastIndex: m.index + m[0].length | ||
| }); | ||
| } | ||
| } | ||
| if (this.__opts__.fuzzyEmail && this.__compiled__['mailto:']) { | ||
| re = this.re.email_fuzzy_global; | ||
| re.lastIndex = 0; | ||
| while ((m = re.exec(text)) !== null) { | ||
| type_fuzzy_email.push({ | ||
| schema: 'mailto:', | ||
| index: m.index + m[1].length, | ||
| lastIndex: m.index + m[0].length | ||
| }); | ||
| } | ||
| } | ||
| const indexes = [0, 0, 0]; | ||
| let lastIndex = 0; | ||
| for (;;) { | ||
| const candidates = [ | ||
| type_schemed[indexes[0]], | ||
| type_fuzzy_email[indexes[1]], | ||
| type_fuzzy_link[indexes[2]] | ||
| ]; | ||
| const candidate = choose(choose(candidates[0], candidates[1]), candidates[2]); | ||
| if (!candidate) { break } | ||
| if (candidate === candidates[0]) { | ||
| indexes[0]++; | ||
| } else if (candidate === candidates[1]) { | ||
| indexes[1]++; | ||
| } else { | ||
| indexes[2]++; | ||
| } | ||
| if (candidate.index < lastIndex) { continue } | ||
| const match = new Match(text, candidate.schema, candidate.index, candidate.lastIndex); | ||
| this.__compiled__[match.schema].normalize(match, this); | ||
| result.push(match); | ||
| lastIndex = candidate.lastIndex; | ||
| } | ||
| if (result.length) { | ||
| return result | ||
| } | ||
| return null | ||
| }; | ||
| /** | ||
| * LinkifyIt#matchAtStart(text) -> Match|null | ||
| * | ||
| * Returns fully-formed (not fuzzy) link if it starts at the beginning | ||
| * of the string, and null otherwise. | ||
| **/ | ||
| LinkifyIt.prototype.matchAtStart = function matchAtStart (text) { | ||
| if (!text.length) return null | ||
| const m = this.re.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.__compiled__[match.schema].normalize(match, this); | ||
| return match | ||
| }; | ||
| /** chainable | ||
| * LinkifyIt#tlds(list [, keepOld]) -> this | ||
| * - list (Array): list of tlds | ||
| * - keepOld (Boolean): merge with current list if `true` (`false` by default) | ||
| * | ||
| * Load (or merge) new tlds list. Those are user for fuzzy links (without prefix) | ||
| * to avoid false positives. By default this algorythm 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. | ||
| **/ | ||
| LinkifyIt.prototype.tlds = function tlds (list, keepOld) { | ||
| list = Array.isArray(list) ? list : [list]; | ||
| if (!keepOld) { | ||
| this.__tlds__ = list.slice(); | ||
| this.__tlds_replaced__ = true; | ||
| compile(this); | ||
| return this | ||
| } | ||
| this.__tlds__ = this.__tlds__.concat(list) | ||
| .sort() | ||
| .filter(function (el, idx, arr) { | ||
| return el !== arr[idx - 1] | ||
| }) | ||
| .reverse(); | ||
| compile(this); | ||
| return this | ||
| }; | ||
| /** | ||
| * LinkifyIt#normalize(match) | ||
| * | ||
| * Default normalizer (if schema does not define it's own). | ||
| **/ | ||
| LinkifyIt.prototype.normalize = function normalize (match) { | ||
| // Do minimal possible changes by default. Need to collect feedback prior | ||
| // to move forward https://github.com/markdown-it/linkify-it/issues/1 | ||
| if (!match.schema) { match.url = `http://${match.url}`; } | ||
| if (match.schema === 'mailto:' && !/^mailto:/i.test(match.url)) { | ||
| match.url = `mailto:${match.url}`; | ||
| } | ||
| }; | ||
| /** | ||
| * LinkifyIt#onCompile() | ||
| * | ||
| * Override to modify basic RegExp-s. | ||
| **/ | ||
| LinkifyIt.prototype.onCompile = function onCompile () { | ||
| }; | ||
| module.exports = LinkifyIt; | ||
| //# sourceMappingURL=index.cjs.js.map |
+18
-18
| { | ||
| "name": "linkify-it", | ||
| "version": "5.0.2", | ||
| "version": "6.0.0", | ||
| "description": "Links recognition library with FULL unicode support", | ||
@@ -13,16 +13,13 @@ "keywords": [ | ||
| "main": "build/index.cjs.js", | ||
| "module": "index.mjs", | ||
| "module": "build/index.mjs", | ||
| "types": "build/index.d.ts", | ||
| "exports": { | ||
| ".": { | ||
| "types": "./build/index.d.ts", | ||
| "require": "./build/index.cjs.js", | ||
| "import": "./index.mjs" | ||
| "import": "./build/index.mjs" | ||
| }, | ||
| "./*": { | ||
| "require": "./*", | ||
| "import": "./*" | ||
| } | ||
| "./package.json": "./package.json" | ||
| }, | ||
| "files": [ | ||
| "index.mjs", | ||
| "lib/", | ||
| "build/" | ||
@@ -43,8 +40,8 @@ ], | ||
| "lint": "eslint .", | ||
| "test": "npm run lint && npm run build && c8 --exclude build --exclude test -r text -r html -r lcov node --test", | ||
| "demo": "npm run lint && node support/build_demo.mjs", | ||
| "doc": "node support/build_doc.mjs", | ||
| "build": "rollup -c support/rollup.config.mjs", | ||
| "gh-pages": "npm run demo && npm run doc && gh-pages -d demo -f", | ||
| "prepack": "npm test && npm run build && npm run demo && npm run doc", | ||
| "type-check": "tsc --noEmit", | ||
| "test": "npm run lint && npm run build && npm run type-check && c8 --exclude build --exclude test -r text -r html -r lcov node --test", | ||
| "doc": "typedoc", | ||
| "build": "node support/build_dist.mjs && node support/build_demo.mjs", | ||
| "gh-pages": "npm run build && npm run doc && gh-pages -d demo -f", | ||
| "prepack": "npm test && npm run doc", | ||
| "postpublish": "npm run gh-pages" | ||
@@ -56,3 +53,2 @@ }, | ||
| "devDependencies": { | ||
| "@rollup/plugin-node-resolve": "^15.2.3", | ||
| "c8": "^11.0.0", | ||
@@ -63,5 +59,9 @@ "eslint": "^9.39.3", | ||
| "neostandard": "^0.13.0", | ||
| "ndoc": "^6.0.0", | ||
| "rollup": "^4.6.1" | ||
| "rollup": "^4.62.2", | ||
| "rollup-plugin-dts": "^6.4.1", | ||
| "typedoc": "^0.28.19", | ||
| "typescript": "^6.0.3", | ||
| "vite": "^8.1.2", | ||
| "vite-plugin-singlefile": "^2.3.3" | ||
| } | ||
| } |
+47
-84
@@ -27,63 +27,37 @@ linkify-it | ||
| Browserification is also supported. | ||
| Usage examples | ||
| -------------- | ||
| ##### Example 1 | ||
| ```js | ||
| import linkifyit from 'linkify-it'; | ||
| const linkify = linkifyit(); | ||
| import { LinkifyIt } from 'linkify-it'; | ||
| const linkify = new LinkifyIt({ fuzzyLink: true }); | ||
| // Reload full tlds list & add unofficial `.onion` domain. | ||
| linkify | ||
| .tlds(require('tlds')) // Reload with full tlds list | ||
| .tlds('onion', true) // Add unofficial `.onion` domain | ||
| .add('git:', 'http:') // Add `git:` protocol as "alias" | ||
| .add('ftp:', null) // Disable `ftp:` protocol | ||
| .set({ fuzzyIP: true }); // Enable IPs in fuzzy links (without schema) | ||
| .tlds(require('tlds')) | ||
| .tlds('onion', true) | ||
| .add('ftp:', null) | ||
| .set({ fuzzyIP: true }); | ||
| console.log(linkify.test('Site github.com!')); // true | ||
| console.log(linkify.test('Site github.com!')); | ||
| // true | ||
| console.log(linkify.match('Site github.com!')); // [ { | ||
| // schema: "", | ||
| // index: 5, | ||
| // lastIndex: 15, | ||
| // raw: "github.com", | ||
| // text: "github.com", | ||
| // url: "http://github.com", | ||
| // } ] | ||
| console.log(linkify.match('Site github.com!')); | ||
| // [ { | ||
| // schema: "", | ||
| // index: 5, | ||
| // lastIndex: 15, | ||
| // raw: "github.com", | ||
| // text: "github.com", | ||
| // url: "http://github.com", | ||
| // } ] | ||
| ``` | ||
| ##### Example 2. Add twitter mentions handler | ||
| See more in examples folder: | ||
| ```js | ||
| linkify.add('@', { | ||
| validate: function (text, pos, self) { | ||
| const tail = text.slice(pos); | ||
| - [twitter mentions](examples/twitter.mjs) | ||
| - [CJK paired brackets in URL paths](examples/cjk-paired-brackets.mjs) | ||
| - [increased nested scopes depth](examples/nested-scopes-depth.mjs) | ||
| if (!self.re.twitter) { | ||
| self.re.twitter = new RegExp( | ||
| `^([a-zA-Z0-9_]){1,15}(?!_)(?=$|${self.re.src_ZPCc})` | ||
| ); | ||
| } | ||
| if (self.re.twitter.test(tail)) { | ||
| // Linkifier allows punctuation chars before prefix, | ||
| // but we additionally disable `@` ("@@mention" is invalid) | ||
| if (pos >= 2 && tail[pos - 2] === '@') { | ||
| return false; | ||
| } | ||
| return tail.match(self.re.twitter)[0].length; | ||
| } | ||
| return 0; | ||
| }, | ||
| normalize: function (match) { | ||
| match.url = `https://twitter.com/${match.url.replace(/^@/, '')}`; | ||
| } | ||
| }); | ||
| ``` | ||
| API | ||
@@ -94,6 +68,5 @@ --- | ||
| ### new LinkifyIt(schemas, options) | ||
| ### new LinkifyIt(options) | ||
| Creates new linkifier instance with optional additional schemas. | ||
| Can be called without `new` keyword for convenience. | ||
| Creates new linkifier instance. | ||
@@ -103,27 +76,17 @@ By default understands: | ||
| - `http(s)://...` , `ftp://...`, `mailto:...` & `//...` links | ||
| - "fuzzy" links and emails (google.com, foo@bar.com). | ||
| - "fuzzy" emails (foo@bar.com). | ||
| `schemas` is an object, where each key/value describes protocol/rule: | ||
| - __key__ - link prefix (usually, protocol name with `:` at the end, `skype:` | ||
| for example). `linkify-it` makes sure that prefix is not preceded with | ||
| alphanumeric char. | ||
| - __value__ - rule to check tail after link prefix | ||
| - _String_ - just alias to existing rule | ||
| - _Object_ | ||
| - _validate_ - either a `RegExp` (start with `^`, and don't include the | ||
| link prefix itself), or a validator function which, given arguments | ||
| _text_, _pos_, and _self_, returns the length of a match in _text_ | ||
| starting at index _pos_. _pos_ is the index right after the link prefix. | ||
| _self_ can be used to access the linkify object to cache data. | ||
| - _normalize_ - optional function to normalize text & url of matched result | ||
| (for example, for twitter mentions). | ||
| `options`: | ||
| - __fuzzyLink__ - recognize URL-s without `http(s)://` head. Default `true`. | ||
| - __fuzzyLink__ - recognize URL-s without `http(s)://` head. Default `false`. | ||
| - __fuzzyIP__ - allow IPs in fuzzy links above. Can conflict with some texts | ||
| like version numbers. Default `false`. | ||
| - __fuzzyEmail__ - recognize emails without `mailto:` prefix. Default `true`. | ||
| - __tlds__ - allowed TLDs list for fuzzy links. Replaces the default list | ||
| when set. | ||
| - __---__ - set `true` to terminate link with `---` (if it's considered as long dash). | ||
| Default `false`. | ||
| - __rebuilder__ - custom `REBuilder` instance for patched regex fragments. | ||
| - __urlAuth__ - recognize authentication data in URLs. Default `false`. | ||
| - __maxLength__ - maximum link length. Default `10000`. | ||
@@ -136,9 +99,2 @@ | ||
| ### .pretest(text) | ||
| Quick check if link MAY BE can exist. Can be used to optimize more expensive | ||
| `.test()` calls. Return `false` if link can not be found, `true` - if `.test()` | ||
| call needed to know exactly. | ||
| ### .testSchemaAt(text, name, offset) | ||
@@ -185,16 +141,23 @@ | ||
| Add a new schema to the schemas object. As described in the constructor | ||
| definition, `key` is a link prefix (`skype:`, for example), and `value` | ||
| is a String to alias to another schema, or an Object with `validate` and | ||
| optionally `normalize` definitions. To disable an existing rule, use | ||
| `.add(key, null)`. | ||
| Add a new schema to the schemas object. | ||
| `key` 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. | ||
| ### .set(options) | ||
| `value` is a rule to check tail after link prefix: | ||
| Override default options. Missed properties will not be changed. | ||
| - _Object_ | ||
| - _validate_ - validator function which, given arguments _text_, _pos_, and | ||
| _self_, returns the length of a match in _text_ starting at index _pos_. | ||
| _pos_ is the index right after the link prefix. _self_ can be used to | ||
| access the linkify object to cache data. | ||
| - _normalize_ - optional function to normalize text & url of matched result | ||
| (for example, for twitter mentions). | ||
| To disable an existing rule, use `.add(key, null)`. | ||
| ## License | ||
| [MIT](https://github.com/markdown-it/linkify-it/blob/master/LICENSE) | ||
| ### .set(options) | ||
| Override default options. Missed properties will not be changed. |
-646
| import reFactory from './lib/re.mjs' | ||
| // | ||
| // Helpers | ||
| // | ||
| // Merge objects | ||
| // | ||
| function assign (obj /* from1, from2, from3, ... */) { | ||
| const sources = Array.prototype.slice.call(arguments, 1) | ||
| sources.forEach(function (source) { | ||
| if (!source) { return } | ||
| Object.keys(source).forEach(function (key) { | ||
| obj[key] = source[key] | ||
| }) | ||
| }) | ||
| return obj | ||
| } | ||
| function _class (obj) { return Object.prototype.toString.call(obj) } | ||
| function isString (obj) { return _class(obj) === '[object String]' } | ||
| function isObject (obj) { return _class(obj) === '[object Object]' } | ||
| function isRegExp (obj) { return _class(obj) === '[object RegExp]' } | ||
| function isFunction (obj) { return _class(obj) === '[object Function]' } | ||
| function escapeRE (str) { return str.replace(/[.?*+^$[\]\\(){}|-]/g, '\\$&') } | ||
| // | ||
| const defaultOptions = { | ||
| fuzzyLink: true, | ||
| fuzzyEmail: true, | ||
| fuzzyIP: false | ||
| } | ||
| function isOptionsObj (obj) { | ||
| return Object.keys(obj || {}).reduce(function (acc, k) { | ||
| /* eslint-disable-next-line no-prototype-builtins */ | ||
| return acc || defaultOptions.hasOwnProperty(k) | ||
| }, false) | ||
| } | ||
| const defaultSchemas = { | ||
| 'http:': { | ||
| validate: function (text, pos, self) { | ||
| const tail = text.slice(pos) | ||
| if (!self.re.http) { | ||
| // compile lazily, because "host"-containing variables can change on tlds update. | ||
| self.re.http = new RegExp( | ||
| `^\\/\\/${self.re.src_auth}${self.re.src_host_port_strict}${self.re.src_path}`, 'i' | ||
| ) | ||
| } | ||
| if (self.re.http.test(tail)) { | ||
| return tail.match(self.re.http)[0].length | ||
| } | ||
| return 0 | ||
| } | ||
| }, | ||
| 'https:': 'http:', | ||
| 'ftp:': 'http:', | ||
| '//': { | ||
| validate: function (text, pos, self) { | ||
| const tail = text.slice(pos) | ||
| if (!self.re.no_http) { | ||
| // compile lazily, because "host"-containing variables can change on tlds update. | ||
| self.re.no_http = new RegExp( | ||
| '^' + | ||
| self.re.src_auth + | ||
| // Don't allow single-level domains, because of false positives like '//test' | ||
| // with code comments | ||
| `(?:localhost|(?:(?:${self.re.src_domain})\\.)+${self.re.src_domain_root})` + | ||
| self.re.src_port + | ||
| self.re.src_host_terminator + | ||
| self.re.src_path, | ||
| 'i' | ||
| ) | ||
| } | ||
| if (self.re.no_http.test(tail)) { | ||
| // should not be `://` & `///`, that protects from errors in protocol name | ||
| if (pos >= 3 && text[pos - 3] === ':') { return 0 } | ||
| if (pos >= 3 && text[pos - 3] === '/') { return 0 } | ||
| return tail.match(self.re.no_http)[0].length | ||
| } | ||
| return 0 | ||
| } | ||
| }, | ||
| 'mailto:': { | ||
| validate: function (text, pos, self) { | ||
| const tail = text.slice(pos) | ||
| if (!self.re.mailto) { | ||
| self.re.mailto = new RegExp( | ||
| `^${self.re.src_email_name}@${self.re.src_host_strict}`, 'i' | ||
| ) | ||
| } | ||
| if (self.re.mailto.test(tail)) { | ||
| return tail.match(self.re.mailto)[0].length | ||
| } | ||
| return 0 | ||
| } | ||
| } | ||
| } | ||
| // RE pattern for 2-character tlds (autogenerated by ./support/tlds_2char_gen.js) | ||
| const tlds_2ch_src_re = '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]|om|p[aefghklmnrstwy]|qa|r[eosuw]|s[abcdeghijklmnortuvxyz]|t[cdfghjklmnortvwz]|u[agksyz]|v[aceginu]|w[fs]|y[et]|z[amw]' | ||
| // DON'T try to make PRs with changes. Extend TLDs with LinkifyIt.tlds() instead | ||
| const tlds_default = 'biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф'.split('|') | ||
| function createValidator (re) { | ||
| return function (text, pos) { | ||
| const tail = text.slice(pos) | ||
| if (re.test(tail)) { | ||
| return tail.match(re)[0].length | ||
| } | ||
| return 0 | ||
| } | ||
| } | ||
| function createNormalizer () { | ||
| return function (match, self) { | ||
| self.normalize(match) | ||
| } | ||
| } | ||
| // Schemas compiler. Build regexps. | ||
| // | ||
| function compile (self) { | ||
| // Load & clone RE patterns. | ||
| const re = self.re = reFactory(self.__opts__) | ||
| // Define dynamic patterns | ||
| const tlds = self.__tlds__.slice() | ||
| self.onCompile() | ||
| if (!self.__tlds_replaced__) { | ||
| tlds.push(tlds_2ch_src_re) | ||
| } | ||
| tlds.push(re.src_xn) | ||
| re.src_tlds = tlds.join('|') | ||
| function untpl (tpl) { return tpl.replace('%TLDS%', re.src_tlds) } | ||
| re.email_fuzzy = RegExp(untpl(re.tpl_email_fuzzy), 'i') | ||
| re.email_fuzzy_global = RegExp(untpl(re.tpl_email_fuzzy), 'ig') | ||
| re.link_fuzzy = RegExp(untpl(re.tpl_link_fuzzy), 'i') | ||
| re.link_fuzzy_global = RegExp(untpl(re.tpl_link_fuzzy), 'ig') | ||
| re.link_no_ip_fuzzy = RegExp(untpl(re.tpl_link_no_ip_fuzzy), 'i') | ||
| re.link_no_ip_fuzzy_global = RegExp(untpl(re.tpl_link_no_ip_fuzzy), 'ig') | ||
| re.host_fuzzy_test = RegExp(untpl(re.tpl_host_fuzzy_test), 'i') | ||
| // | ||
| // Compile each schema | ||
| // | ||
| const aliases = [] | ||
| self.__compiled__ = {} // Reset compiled data | ||
| function schemaError (name, val) { | ||
| throw new Error(`(LinkifyIt) Invalid schema "${name}": ${val}`) | ||
| } | ||
| Object.keys(self.__schemas__).forEach(function (name) { | ||
| const val = self.__schemas__[name] | ||
| // skip disabled methods | ||
| if (val === null) { return } | ||
| const compiled = { validate: null, link: null } | ||
| self.__compiled__[name] = compiled | ||
| if (isObject(val)) { | ||
| if (isRegExp(val.validate)) { | ||
| compiled.validate = createValidator(val.validate) | ||
| } else if (isFunction(val.validate)) { | ||
| compiled.validate = val.validate | ||
| } else { | ||
| schemaError(name, val) | ||
| } | ||
| if (isFunction(val.normalize)) { | ||
| compiled.normalize = val.normalize | ||
| } else if (!val.normalize) { | ||
| compiled.normalize = createNormalizer() | ||
| } else { | ||
| schemaError(name, val) | ||
| } | ||
| return | ||
| } | ||
| if (isString(val)) { | ||
| aliases.push(name) | ||
| return | ||
| } | ||
| schemaError(name, val) | ||
| }) | ||
| // | ||
| // Compile postponed aliases | ||
| // | ||
| aliases.forEach(function (alias) { | ||
| if (!self.__compiled__[self.__schemas__[alias]]) { | ||
| // Silently fail on missed schemas to avoid errons on disable. | ||
| // schemaError(alias, self.__schemas__[alias]); | ||
| return | ||
| } | ||
| self.__compiled__[alias].validate = | ||
| self.__compiled__[self.__schemas__[alias]].validate | ||
| self.__compiled__[alias].normalize = | ||
| self.__compiled__[self.__schemas__[alias]].normalize | ||
| }) | ||
| // | ||
| // Fake record for guessed links | ||
| // | ||
| self.__compiled__[''] = { validate: null, normalize: createNormalizer() } | ||
| // | ||
| // Build schema condition | ||
| // | ||
| const slist = Object.keys(self.__compiled__) | ||
| .filter(function (name) { | ||
| // Filter disabled & fake schemas | ||
| return name.length > 0 && self.__compiled__[name] | ||
| }) | ||
| .map(escapeRE) | ||
| .join('|') | ||
| // (?!_) cause 1.5x slowdown | ||
| self.re.schema_test = RegExp(`(^|(?!_)(?:[><\uff5c]|${re.src_ZPCc}))(${slist})`, 'i') | ||
| self.re.schema_search = RegExp(`(^|(?!_)(?:[><\uff5c]|${re.src_ZPCc}))(${slist})`, 'ig') | ||
| self.re.schema_at_start = RegExp(`^${self.re.schema_search.source}`, 'i') | ||
| self.re.pretest = RegExp( | ||
| `(${self.re.schema_test.source})|(${self.re.host_fuzzy_test.source})|@`, | ||
| 'i' | ||
| ) | ||
| } | ||
| /** | ||
| * class Match | ||
| * | ||
| * Match result. Single element of array, returned by [[LinkifyIt#match]] | ||
| **/ | ||
| function Match (text, schema, index, lastIndex) { | ||
| const raw = text.slice(index, lastIndex) | ||
| /** | ||
| * Match#schema -> String | ||
| * | ||
| * Prefix (protocol) for matched string. | ||
| **/ | ||
| this.schema = schema.toLowerCase() | ||
| /** | ||
| * Match#index -> Number | ||
| * | ||
| * First position of matched string. | ||
| **/ | ||
| this.index = index | ||
| /** | ||
| * Match#lastIndex -> Number | ||
| * | ||
| * Next position after matched string. | ||
| **/ | ||
| this.lastIndex = lastIndex | ||
| /** | ||
| * Match#raw -> String | ||
| * | ||
| * Matched string. | ||
| **/ | ||
| this.raw = raw | ||
| /** | ||
| * Match#text -> String | ||
| * | ||
| * Notmalized text of matched string. | ||
| **/ | ||
| this.text = raw | ||
| /** | ||
| * Match#url -> String | ||
| * | ||
| * Normalized url of matched string. | ||
| **/ | ||
| this.url = raw | ||
| } | ||
| /** | ||
| * class LinkifyIt | ||
| **/ | ||
| /** | ||
| * new LinkifyIt(schemas, options) | ||
| * - schemas (Object): Optional. Additional schemas to validate (prefix/validator) | ||
| * - options (Object): { fuzzyLink|fuzzyEmail|fuzzyIP: true|false } | ||
| * | ||
| * Creates new linkifier instance with optional additional schemas. | ||
| * Can be called without `new` keyword for convenience. | ||
| * | ||
| * By default understands: | ||
| * | ||
| * - `http(s)://...` , `ftp://...`, `mailto:...` & `//...` links | ||
| * - "fuzzy" links and emails (example.com, foo@bar.com). | ||
| * | ||
| * `schemas` is an object, where each key/value describes protocol/rule: | ||
| * | ||
| * - __key__ - link prefix (usually, protocol name with `:` at the end, `skype:` | ||
| * for example). `linkify-it` makes shure that prefix is not preceeded with | ||
| * alphanumeric char and symbols. Only whitespaces and punctuation allowed. | ||
| * - __value__ - rule to check tail after link prefix | ||
| * - _String_ - just alias to existing rule | ||
| * - _Object_ | ||
| * - _validate_ - validator function (should return matched length on success), | ||
| * or `RegExp`. | ||
| * - _normalize_ - optional function to normalize text & url of matched result | ||
| * (for example, for @twitter mentions). | ||
| * | ||
| * `options`: | ||
| * | ||
| * - __fuzzyLink__ - recognige URL-s without `http(s):` prefix. Default `true`. | ||
| * - __fuzzyIP__ - allow IPs in fuzzy links above. Can conflict with some texts | ||
| * like version numbers. Default `false`. | ||
| * - __fuzzyEmail__ - recognize emails without `mailto:` prefix. | ||
| * | ||
| **/ | ||
| function LinkifyIt (schemas, options) { | ||
| if (!(this instanceof LinkifyIt)) { | ||
| return new LinkifyIt(schemas, options) | ||
| } | ||
| if (!options) { | ||
| if (isOptionsObj(schemas)) { | ||
| options = schemas | ||
| schemas = {} | ||
| } | ||
| } | ||
| this.__opts__ = assign({}, defaultOptions, options) | ||
| this.__schemas__ = assign({}, defaultSchemas, schemas) | ||
| this.__compiled__ = {} | ||
| this.__tlds__ = tlds_default | ||
| this.__tlds_replaced__ = false | ||
| this.re = {} | ||
| compile(this) | ||
| } | ||
| /** chainable | ||
| * LinkifyIt#add(schema, definition) | ||
| * - schema (String): rule name (fixed pattern prefix) | ||
| * - definition (String|RegExp|Object): schema definition | ||
| * | ||
| * Add new rule definition. See constructor description for details. | ||
| **/ | ||
| LinkifyIt.prototype.add = function add (schema, definition) { | ||
| this.__schemas__[schema] = definition | ||
| compile(this) | ||
| return this | ||
| } | ||
| /** chainable | ||
| * LinkifyIt#set(options) | ||
| * - options (Object): { fuzzyLink|fuzzyEmail|fuzzyIP: true|false } | ||
| * | ||
| * Set recognition options for links without schema. | ||
| **/ | ||
| LinkifyIt.prototype.set = function set (options) { | ||
| this.__opts__ = assign(this.__opts__, options) | ||
| return this | ||
| } | ||
| /** | ||
| * LinkifyIt#test(text) -> Boolean | ||
| * | ||
| * Searches linkifiable pattern and returns `true` on success or `false` on fail. | ||
| **/ | ||
| LinkifyIt.prototype.test = function test (text) { | ||
| if (!text.length) { return false } | ||
| let m, re | ||
| // try to scan for link with schema - that's the most simple rule | ||
| if (this.re.schema_test.test(text)) { | ||
| re = this.re.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.__compiled__['http:']) { | ||
| // guess schemaless links | ||
| if (text.search(this.re.host_fuzzy_test) >= 0) { | ||
| if (text.match(this.__opts__.fuzzyIP ? this.re.link_fuzzy : this.re.link_no_ip_fuzzy) !== null) { | ||
| return true | ||
| } | ||
| } | ||
| } | ||
| if (this.__opts__.fuzzyEmail && this.__compiled__['mailto:']) { | ||
| // guess schemaless emails | ||
| if (text.indexOf('@') >= 0) { | ||
| // We can't skip this check, because this cases are possible: | ||
| // 192.168.1.1@gmail.com, my.in@example.com | ||
| if (text.match(this.re.email_fuzzy) !== null) { return true } | ||
| } | ||
| } | ||
| return false | ||
| } | ||
| /** | ||
| * LinkifyIt#pretest(text) -> Boolean | ||
| * | ||
| * Very quick check, that can give false positives. Returns true if link MAY BE | ||
| * can exists. Can be used for speed optimization, when you need to check that | ||
| * link NOT exists. | ||
| **/ | ||
| LinkifyIt.prototype.pretest = function pretest (text) { | ||
| return this.re.pretest.test(text) | ||
| } | ||
| /** | ||
| * LinkifyIt#testSchemaAt(text, name, position) -> Number | ||
| * - text (String): text to scan | ||
| * - name (String): rule (schema) name | ||
| * - position (Number): text offset to check from | ||
| * | ||
| * Similar to [[LinkifyIt#test]] but checks only specific protocol tail exactly | ||
| * at given position. Returns length of found pattern (0 on fail). | ||
| **/ | ||
| LinkifyIt.prototype.testSchemaAt = function testSchemaAt (text, schema, pos) { | ||
| // If not supported schema check requested - terminate | ||
| if (!this.__compiled__[schema.toLowerCase()]) { | ||
| return 0 | ||
| } | ||
| return this.__compiled__[schema.toLowerCase()].validate(text, pos, this) | ||
| } | ||
| /** | ||
| * LinkifyIt#match(text) -> Array|null | ||
| * | ||
| * Returns array of found link descriptions or `null` on fail. We strongly | ||
| * recommend to use [[LinkifyIt#test]] first, for best speed. | ||
| * | ||
| * ##### Result match description | ||
| * | ||
| * - __schema__ - link schema, can be empty for fuzzy links, or `//` for | ||
| * protocol-neutral links. | ||
| * - __index__ - offset of matched text | ||
| * - __lastIndex__ - index of next char after mathch end | ||
| * - __raw__ - matched text | ||
| * - __text__ - normalized text | ||
| * - __url__ - link, generated from matched text | ||
| **/ | ||
| LinkifyIt.prototype.match = function match (text) { | ||
| const result = [] | ||
| const type_schemed = [] | ||
| const type_fuzzy_link = [] | ||
| const type_fuzzy_email = [] | ||
| let m, len, re | ||
| function choose (a, b) { | ||
| if (!a) { return b } | ||
| if (!b) { return a } | ||
| if (a.index !== b.index) { return a.index < b.index ? a : b } | ||
| return a.lastIndex >= b.lastIndex ? a : b | ||
| } | ||
| if (!text.length) { return null } | ||
| // scan for links with schema | ||
| if (this.re.schema_test.test(text)) { | ||
| re = this.re.schema_search | ||
| re.lastIndex = 0 | ||
| while ((m = re.exec(text)) !== null) { | ||
| len = this.testSchemaAt(text, m[2], re.lastIndex) | ||
| if (len) { | ||
| type_schemed.push({ | ||
| schema: m[2], | ||
| index: m.index + m[1].length, | ||
| lastIndex: m.index + m[0].length + len | ||
| }) | ||
| } | ||
| } | ||
| } | ||
| if (this.__opts__.fuzzyLink && this.__compiled__['http:']) { | ||
| re = this.__opts__.fuzzyIP ? this.re.link_fuzzy_global : this.re.link_no_ip_fuzzy_global | ||
| re.lastIndex = 0 | ||
| while ((m = re.exec(text)) !== null) { | ||
| type_fuzzy_link.push({ | ||
| schema: '', | ||
| index: m.index + m[1].length, | ||
| lastIndex: m.index + m[0].length | ||
| }) | ||
| } | ||
| } | ||
| if (this.__opts__.fuzzyEmail && this.__compiled__['mailto:']) { | ||
| re = this.re.email_fuzzy_global | ||
| re.lastIndex = 0 | ||
| while ((m = re.exec(text)) !== null) { | ||
| type_fuzzy_email.push({ | ||
| schema: 'mailto:', | ||
| index: m.index + m[1].length, | ||
| lastIndex: m.index + m[0].length | ||
| }) | ||
| } | ||
| } | ||
| const indexes = [0, 0, 0] | ||
| let lastIndex = 0 | ||
| for (;;) { | ||
| const candidates = [ | ||
| type_schemed[indexes[0]], | ||
| type_fuzzy_email[indexes[1]], | ||
| type_fuzzy_link[indexes[2]] | ||
| ] | ||
| const candidate = choose(choose(candidates[0], candidates[1]), candidates[2]) | ||
| if (!candidate) { break } | ||
| if (candidate === candidates[0]) { | ||
| indexes[0]++ | ||
| } else if (candidate === candidates[1]) { | ||
| indexes[1]++ | ||
| } else { | ||
| indexes[2]++ | ||
| } | ||
| if (candidate.index < lastIndex) { continue } | ||
| const match = new Match(text, candidate.schema, candidate.index, candidate.lastIndex) | ||
| this.__compiled__[match.schema].normalize(match, this) | ||
| result.push(match) | ||
| lastIndex = candidate.lastIndex | ||
| } | ||
| if (result.length) { | ||
| return result | ||
| } | ||
| return null | ||
| } | ||
| /** | ||
| * LinkifyIt#matchAtStart(text) -> Match|null | ||
| * | ||
| * Returns fully-formed (not fuzzy) link if it starts at the beginning | ||
| * of the string, and null otherwise. | ||
| **/ | ||
| LinkifyIt.prototype.matchAtStart = function matchAtStart (text) { | ||
| if (!text.length) return null | ||
| const m = this.re.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.__compiled__[match.schema].normalize(match, this) | ||
| return match | ||
| } | ||
| /** chainable | ||
| * LinkifyIt#tlds(list [, keepOld]) -> this | ||
| * - list (Array): list of tlds | ||
| * - keepOld (Boolean): merge with current list if `true` (`false` by default) | ||
| * | ||
| * Load (or merge) new tlds list. Those are user for fuzzy links (without prefix) | ||
| * to avoid false positives. By default this algorythm 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. | ||
| **/ | ||
| LinkifyIt.prototype.tlds = function tlds (list, keepOld) { | ||
| list = Array.isArray(list) ? list : [list] | ||
| if (!keepOld) { | ||
| this.__tlds__ = list.slice() | ||
| this.__tlds_replaced__ = true | ||
| compile(this) | ||
| return this | ||
| } | ||
| this.__tlds__ = this.__tlds__.concat(list) | ||
| .sort() | ||
| .filter(function (el, idx, arr) { | ||
| return el !== arr[idx - 1] | ||
| }) | ||
| .reverse() | ||
| compile(this) | ||
| return this | ||
| } | ||
| /** | ||
| * LinkifyIt#normalize(match) | ||
| * | ||
| * Default normalizer (if schema does not define it's own). | ||
| **/ | ||
| LinkifyIt.prototype.normalize = function normalize (match) { | ||
| // Do minimal possible changes by default. Need to collect feedback prior | ||
| // to move forward https://github.com/markdown-it/linkify-it/issues/1 | ||
| if (!match.schema) { match.url = `http://${match.url}` } | ||
| if (match.schema === 'mailto:' && !/^mailto:/i.test(match.url)) { | ||
| match.url = `mailto:${match.url}` | ||
| } | ||
| } | ||
| /** | ||
| * LinkifyIt#onCompile() | ||
| * | ||
| * Override to modify basic RegExp-s. | ||
| **/ | ||
| LinkifyIt.prototype.onCompile = function onCompile () { | ||
| } | ||
| export default LinkifyIt |
-193
| import { Any, Cc, Z, P } from 'uc.micro' | ||
| export default function (opts) { | ||
| const re = {} | ||
| opts = opts || {} | ||
| re.src_Any = Any.source | ||
| re.src_Cc = Cc.source | ||
| re.src_Z = Z.source | ||
| re.src_P = P.source | ||
| // \p{\Z\P\Cc\CF} (white spaces + control + format + punctuation) | ||
| re.src_ZPCc = [re.src_Z, re.src_P, re.src_Cc].join('|') | ||
| // \p{\Z\Cc} (white spaces + control) | ||
| re.src_ZCc = [re.src_Z, re.src_Cc].join('|') | ||
| // Experimental. List of chars, completely prohibited in links | ||
| // because can separate it from other part of text | ||
| const text_separators = '[><\uff5c]' | ||
| // All possible word characters (everything without punctuation, spaces & controls) | ||
| // Defined via punctuation & spaces to save space | ||
| // Should be something like \p{\L\N\S\M} (\w but without `_`) | ||
| re.src_pseudo_letter = `(?:(?!${text_separators}|${re.src_ZPCc})${re.src_Any})` | ||
| // The same as abothe but without [0-9] | ||
| // var src_pseudo_letter_non_d = '(?:(?![0-9]|' + src_ZPCc + ')' + src_Any + ')'; | ||
| re.src_ip4 = | ||
| '(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)' | ||
| // Prohibit any of "@/[]()" in user/pass to avoid wrong domain fetch. | ||
| // Length is capped to exclude possible rescans till the end and avoid O(n^2) | ||
| // DoS. No standard limit, just take something reasonable. | ||
| re.src_auth = `(?:(?:(?!${re.src_ZCc}|[@/\\[\\]()]).){1,50}@)?` | ||
| re.src_port = | ||
| '(?::(?:6(?:[0-4]\\d{3}|5(?:[0-4]\\d{2}|5(?:[0-2]\\d|3[0-5])))|[1-5]?\\d{1,4}))?' | ||
| re.src_host_terminator = | ||
| `(?=$|${text_separators}|${re.src_ZPCc})` + | ||
| `(?!${opts['---'] ? '-(?!--)|' : '-|'}_|:\\d|\\.-|\\.(?!$|${re.src_ZPCc}))` | ||
| re.src_path = | ||
| '(?:' + | ||
| '[/?#]' + | ||
| '(?:' + | ||
| `(?!${re.src_ZCc}|${text_separators}|[()[\\]{}.,"'?!\\-;]).|` + | ||
| `\\[(?:(?!${re.src_ZCc}|\\]).)*\\]|` + | ||
| `\\((?:(?!${re.src_ZCc}|[)]).)*\\)|` + | ||
| `\\{(?:(?!${re.src_ZCc}|[}]).)*\\}|` + | ||
| `\\"(?:(?!${re.src_ZCc}|["]).)+\\"|` + | ||
| `\\'(?:(?!${re.src_ZCc}|[']).)+\\'|` + | ||
| // allow `I'm_king` if no pair found | ||
| `\\'(?=${re.src_pseudo_letter}|[-])|` + | ||
| // google has many dots in "google search" links (#66, #81). | ||
| // github has ... in commit range links, | ||
| // Restrict to | ||
| // - english | ||
| // - percent-encoded | ||
| // - parts of file path | ||
| // - params separator | ||
| // until more examples found. | ||
| '\\.{2,}[a-zA-Z0-9%/&]|' + | ||
| `\\.(?!${re.src_ZCc}|[.]|$)|` + | ||
| (opts['---'] | ||
| ? '\\-(?!--(?:[^-]|$))(?:-*)|' // `---` => long dash, terminate | ||
| : '\\-+|' | ||
| ) + | ||
| // allow `,,,` in paths | ||
| `,(?!${re.src_ZCc}|$)|` + | ||
| // allow `;` if not followed by space-like char | ||
| `;(?!${re.src_ZCc}|$)|` + | ||
| // allow `!!!` in paths, but not at the end | ||
| `\\!+(?!${re.src_ZCc}|[!]|$)|` + | ||
| `\\?(?!${re.src_ZCc}|[?]|$)` + | ||
| ')+' + | ||
| '|\\/' + | ||
| ')?' | ||
| // Allow anything in markdown spec, forbid quote (") at the first position | ||
| // because emails enclosed in quotes are far more common | ||
| // Max name length capped to 64 chars (RFC 5321). This also prevents O(n^2) | ||
| // rescans to the end on inputs like `mailto:mailto:...` | ||
| re.src_email_name = | ||
| '[\\-;:&=\\+\\$,\\.a-zA-Z0-9_][\\-;:&=\\+\\$,\\"\\.a-zA-Z0-9_]{0,63}' | ||
| re.src_xn = | ||
| 'xn--[a-z0-9\\-]{1,59}' | ||
| // More to read about domain names | ||
| // http://serverfault.com/questions/638260/ | ||
| re.src_domain_root = | ||
| // Allow letters & digits (http://test1) | ||
| '(?:' + | ||
| re.src_xn + | ||
| '|' + | ||
| `${re.src_pseudo_letter}{1,63}` + | ||
| ')' | ||
| re.src_domain = | ||
| '(?:' + | ||
| re.src_xn + | ||
| '|' + | ||
| `(?:${re.src_pseudo_letter})` + | ||
| '|' + | ||
| `(?:${re.src_pseudo_letter}(?:-|${re.src_pseudo_letter}){0,61}${re.src_pseudo_letter})` + | ||
| ')' | ||
| re.src_host = | ||
| '(?:' + | ||
| // Don't need IP check, because digits are already allowed in normal domain names | ||
| // src_ip4 + | ||
| // '|' + | ||
| `(?:(?:(?:${re.src_domain})\\.)*${re.src_domain})`/* _root */ + | ||
| ')' | ||
| re.tpl_host_fuzzy = | ||
| '(?:' + | ||
| re.src_ip4 + | ||
| '|' + | ||
| `(?:(?:(?:${re.src_domain})\\.)+(?:%TLDS%))` + | ||
| ')' | ||
| re.tpl_host_no_ip_fuzzy = | ||
| `(?:(?:(?:${re.src_domain})\\.)+(?:%TLDS%))` | ||
| re.src_host_strict = | ||
| re.src_host + re.src_host_terminator | ||
| re.tpl_host_fuzzy_strict = | ||
| re.tpl_host_fuzzy + re.src_host_terminator | ||
| re.src_host_port_strict = | ||
| re.src_host + re.src_port + re.src_host_terminator | ||
| re.tpl_host_port_fuzzy_strict = | ||
| re.tpl_host_fuzzy + re.src_port + re.src_host_terminator | ||
| re.tpl_host_port_no_ip_fuzzy_strict = | ||
| re.tpl_host_no_ip_fuzzy + re.src_port + re.src_host_terminator | ||
| // | ||
| // Main rules | ||
| // | ||
| // Rude test fuzzy links by host, for quick deny | ||
| re.tpl_host_fuzzy_test = | ||
| `localhost|www\\.|\\.\\d{1,3}\\.|(?:\\.(?:%TLDS%)(?:${re.src_ZPCc}|>|$))` | ||
| re.tpl_email_fuzzy = | ||
| `(^|${text_separators}|"|\\(|${re.src_ZCc})` + | ||
| `(${re.src_email_name}@${re.tpl_host_fuzzy_strict})` | ||
| re.tpl_link_fuzzy = | ||
| // Fuzzy link can't be prepended with .:/\- and non punctuation. | ||
| // but can start with > (markdown blockquote) | ||
| `(^|(?![.:/\\-_@])(?:[$+<=>^\`|\uff5c]|${re.src_ZPCc}))` + | ||
| `((?![$+<=>^\`|\uff5c])${re.tpl_host_port_fuzzy_strict}${re.src_path})` | ||
| re.tpl_link_no_ip_fuzzy = | ||
| // Fuzzy link can't be prepended with .:/\- and non punctuation. | ||
| // but can start with > (markdown blockquote) | ||
| `(^|(?![.:/\\-_@])(?:[$+<=>^\`|\uff5c]|${re.src_ZPCc}))` + | ||
| `((?![$+<=>^\`|\uff5c])${re.tpl_host_port_no_ip_fuzzy_strict}${re.src_path})` | ||
| return re | ||
| } |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
149127
167.25%8
33.33%1440
4.35%11
37.5%159
-18.88%1
Infinity%