import { Injectable } from '@angular/core' import { getAbsoluteAPIUrl } from '@app/shared/misc/utils' import * as linkify from 'linkifyjs' import * as linkifyHtml from 'linkifyjs/html' @Injectable() export class LinkifierService { static CLASSNAME = 'linkified' private linkifyOptions = { className: { mention: LinkifierService.CLASSNAME + '-mention', url: LinkifierService.CLASSNAME + '-url' } } constructor () { // Apply plugin this.mentionWithDomainPlugin(linkify) } linkify (text: string) { return linkifyHtml(text, this.linkifyOptions) } private mentionWithDomainPlugin (linkify: any) { const TT = linkify.scanner.TOKENS // Text tokens const { TOKENS: MT, State } = linkify.parser // Multi tokens, state const MultiToken = MT.Base const S_START = linkify.parser.start const TT_AT = TT.AT const TT_DOMAIN = TT.DOMAIN const TT_LOCALHOST = TT.LOCALHOST const TT_NUM = TT.NUM const TT_COLON = TT.COLON const TT_SLASH = TT.SLASH const TT_TLD = TT.TLD const TT_UNDERSCORE = TT.UNDERSCORE const TT_DOT = TT.DOT function MENTION (value) { this.v = value } linkify.inherits(MultiToken, MENTION, { type: 'mentionWithDomain', isLink: true, toHref () { return getAbsoluteAPIUrl() + '/services/redirect/accounts/' + this.toString().substr(1) } }) const S_AT = S_START.jump(TT_AT) // @ const S_AT_SYMS = new State() const S_MENTION = new State(MENTION) const S_MENTION_DIVIDER = new State() const S_MENTION_DIVIDER_SYMS = new State() // @_, S_AT.on(TT_UNDERSCORE, S_AT_SYMS) // @_* S_AT_SYMS .on(TT_UNDERSCORE, S_AT_SYMS) .on(TT_DOT, S_AT_SYMS) // Valid mention (not made up entirely of symbols) S_AT .on(TT_DOMAIN, S_MENTION) .on(TT_LOCALHOST, S_MENTION) .on(TT_TLD, S_MENTION) .on(TT_NUM, S_MENTION) S_AT_SYMS .on(TT_DOMAIN, S_MENTION) .on(TT_LOCALHOST, S_MENTION) .on(TT_TLD, S_MENTION) .on(TT_NUM, S_MENTION) // More valid mentions S_MENTION .on(TT_DOMAIN, S_MENTION) .on(TT_LOCALHOST, S_MENTION) .on(TT_TLD, S_MENTION) .on(TT_COLON, S_MENTION) .on(TT_NUM, S_MENTION) .on(TT_UNDERSCORE, S_MENTION) // Mention with a divider S_MENTION .on(TT_AT, S_MENTION_DIVIDER) .on(TT_SLASH, S_MENTION_DIVIDER) .on(TT_DOT, S_MENTION_DIVIDER) // Mention _ trailing stash plus syms S_MENTION_DIVIDER.on(TT_UNDERSCORE, S_MENTION_DIVIDER_SYMS) S_MENTION_DIVIDER_SYMS.on(TT_UNDERSCORE, S_MENTION_DIVIDER_SYMS) // Once we get a word token, mentions can start up again S_MENTION_DIVIDER .on(TT_DOMAIN, S_MENTION) .on(TT_LOCALHOST, S_MENTION) .on(TT_TLD, S_MENTION) .on(TT_NUM, S_MENTION) S_MENTION_DIVIDER_SYMS .on(TT_DOMAIN, S_MENTION) .on(TT_LOCALHOST, S_MENTION) .on(TT_TLD, S_MENTION) .on(TT_NUM, S_MENTION) } }