Autolinker.js icon indicating copy to clipboard operation
Autolinker.js copied to clipboard

Custom matcher

Open kakone opened this issue 6 years ago • 4 comments

Hello,

Thanks for this great library, it's very useful. I wanted to add my own custom matcher to the matchers list. I tried this code and it works great :

let autolinker = new Autolinker();
let tagBuilder = (<any>autolinker).getTagBuilder();
(<any>autolinker).getMatchers().push(new CustomMatcher({ tagBuilder }));

So, could you make the getTagBuilder and getMatchers methods public? With these two public methods, it will be easy to add a custom matcher. Or is there another easy way to add a custom matcher ?

Cordially, Stephane.

kakone avatar Oct 04 '19 13:10 kakone

Thanks Stephane, your snippet helped me register a custom matcher for Amazon's ARNs, based on the Mention matcher and match source

It'd be great to see this extension use case supported without hacks like this :) Especially considering how readable and well documented the current matchers are.

Maybe it could be an extra argument passed into the Autolinker constructor even.

domjancik avatar Mar 21 '21 08:03 domjancik

Unfortunately, @gregjacobs broke everything in version 4 :smiley:. It's seems to be hard to add a custom matcher now. I will try to propose a PR when I have time but for the moment, I stay in version 3.6.12.

kakone avatar Oct 14 '22 11:10 kakone

Hey @kakone, apologies! Can you tell me more about your custom matcher use case? What are you matching exactly?

I'm trying to figure out how to best allow for this custom matchers scenario. In v4.0, I changed how matching worked to combine all of the previous "matchers" into one single non-deterministic finite state machine for performance reasons. (Autolinker previously walked through the input string one time for each matcher, and now only walks through the input string exactly once.)

Are you looking to match on a regular expression? Curious as to what your current CustomMatcher class looks like.

Best, Greg

gregjacobs avatar Oct 14 '22 16:10 gregjacobs

I use autolink to handle the URLs and email adresses but I add a custom matcher for my business app : I detect the orders numbers (some purchase orders, repair orders, ...) to create a link to my web app. This is the source code of my custom matcher :

export class OrderNumberMatcher extends Matcher {
    private ordersUrls;

    constructor(cfg: MatcherConfig, ordersUrls) {
        super(cfg);
        this.ordersUrls = ordersUrls;
    }    
    
    parseMatches(text: string) {
        let matches: Match[] = [],
            match: RegExpExecArray | null;

        for (let regExp in this.ordersUrls) {
            let regularExpression = new RegExp(regExp, "g");
            while ((match = regularExpression.exec(text)) !== null) {
                matches.push(new OrderNumberMatch({
                    tagBuilder: this.tagBuilder,
                    matchedText: match[0],
                    offset: match.index
                }, this.ordersUrls[regExp]));
            }
        }

        return matches;
    }
}

ordersUrls is a dictionary where the key is a regex and the value an URL with {0} that will be replaced by the order number.

So, my OrderNumberMatch is like this :

export class OrderNumberMatch extends Match {	
    private url: string;

    constructor(cfg: MatchConfig, url: string) {
        super(cfg);
        this.url = url;
    }
	
    getType() {
        return 'orderNumber';
    }
	
    getAnchorHref() {
        return this.url.replace("{0}", this.matchedText);
    }

    getAnchorText() {
        return this.matchedText;
    }
}

kakone avatar Oct 14 '22 17:10 kakone