Hypercontext / linkifyjs

JavaScript plugin for finding links in plain-text and converting them to HTML <a> tags.
https://linkify.js.org
MIT License
1.83k stars 182 forks source link

Linkify js do not find URL with question mark? #474

Closed onigetoc closed 6 months ago

onigetoc commented 6 months ago

I'm in a Ionic project and Linkify js do not find URL with question mark? Is there a conflict with Ionic Angular, or security problems? I don't know

nfrasser commented 6 months ago

Hi @onigetoc, could you please post an example URL that reproduces this issue?

onigetoc commented 6 months ago

Hi @nfrasser All urls work except the one with a question mark. in my test i put this url https://www.chess.com/analysis/game/live/53408409959?tab=review If i replace the link question mark with %3F it will work. But the http url is added by the user and i can't control that. I tried to make a simple replace but it do not work.

onigetoc commented 6 months ago

@nfrasser. This is how i do it in my home.page.ts

I tried with linkify-html and mention and hashtag plugin but it didn't work. The i did it this was with :

import * as linkify from 'linkifyjs';
import "linkify-plugin-hashtag";
import "linkify-plugin-mention";
  linkifier(text: string): string {

    //GC replace question marks with %3F
    // text = text.replace(/\?/g, '%3F')

    // Convertir les mentions en liens avec les options de formatHref
    const linkifiedTextArray = linkify.find(text, {
        formatHref: {
            mention: (href: string) => "https://twitter.com" + href,
            hashtag: (href: string) => "https://twitter.com/hashtag/" + href.substring(1), // Supprimer le "#" de la valeur href
        }
    });

    // Créer une fonction pour remplacer les mentions par des liens
    const replaceMentionsWithLinks = (inputText: string): string => {
        let outputText = inputText;
        linkifiedTextArray.forEach(linkObj => {
            const mentionRegex = new RegExp(linkObj.value, 'g');
            outputText = outputText.replace(mentionRegex, `<a href="${linkObj.href}" target="_blank">${linkObj.value}</a>`);
        });
        return outputText;
    };

    // text = text.replace(/\%3F/g, '?')

    const textWithMentionsLinked = replaceMentionsWithLinks(text);

    return textWithMentionsLinked;
}
onigetoc commented 6 months ago

I just find now that the right url with a question mark is in the Array but it cannot replace it ?? I do not understand why, and if i remove the question mark or replace with & or %3F in the origal text it will work.

[
    {
        "type": "hashtag",
        "value": "#test",
        "isLink": true,
        "href": "https://twitter.com/hashtag/test",
        "start": 46,
        "end": 51
    },
    {
        "type": "email",
        "value": "blablabla@hotmail.com",
        "isLink": true,
        "href": "mailto:blablabla@hotmail.com",
        "start": 101,
        "end": 122
    },
    {
        "type": "mention",
        "value": "@chesscom",
        "isLink": true,
        "href": "https://twitter.com/chesscom",
        "start": 386,
        "end": 395
    },
    {
        "type": "url",
        "value": "https://www.chess.com/analysis/game/live/53408409959?tab=review",
        "isLink": true,
        "href": "https://www.chess.com/analysis/game/live/53408409959?tab=review",
        "start": 403,
        "end": 466
    },
    {
        "type": "hashtag",
        "value": "#chesscom",
        "isLink": true,
        "href": "https://twitter.com/hashtag/chesscom",
        "start": 483,
        "end": 492
    },
    {
        "type": "url",
        "value": "https://www.example.com/page1",
        "isLink": true,
        "href": "https://www.example.com/page1",
        "start": 495,
        "end": 524
    },
    {
        "type": "url",
        "value": "https://www.example.com/page2",
        "isLink": true,
        "href": "https://www.example.com/page2",
        "start": 528,
        "end": 557
    }
]
onigetoc commented 6 months ago

chatGPT did help me lol. Adding a escapedValue did the job.

    const replaceMentionsWithLinks = (inputText: string): string => {
      let outputText = inputText;
      linkifiedTextArray.forEach(linkObj => {
          // Échapper le point d'interrogation dans le regex
          const escapedValue = linkObj.value.replace(/\?/g, "\\?");
          const twitterRegex = new RegExp(escapedValue, 'gi');
          outputText = outputText.replace(twitterRegex, `<a href="${linkObj.href}" target="_blank">${linkObj.value}</a>`);
      });
      return outputText;
  };
nfrasser commented 6 months ago

@onigetoc I think this has to do with your Regex replacement strategy, it should work if you replace:

const mentionRegex = new RegExp(linkObj.value, 'g');

With

const mentionRegex = linkObj.value;

HOWEVER, I strongly recommend you DO NOT use this strategy. This will fail if the same link is included twice, e.g.,

linkifier("chess.com chess.com")

Instead, use the linkify-string package for this: https://linkify.js.org/docs/linkify-string.html

This depends on linkify and implements the linkifier functionality you have as safely as possible.