Angular2将纯文本转换为url的方式(锚链接)

Posted

技术标签:

【中文标题】Angular2将纯文本转换为url的方式(锚链接)【英文标题】:Angular2 way of converting plain text to url (anchor links) 【发布时间】:2017-01-09 15:19:15 【问题描述】:

我有时有一个组件可以接收这样的文本:

文本 www.website.com

但如果是链接,我想将其转换为 url。像这样。

文字www.website.com

我读到这个SO answer 建议使用第三方库,例如anchorme。有没有办法以angular2方式做到这一点?

【问题讨论】:

这有什么问题? 【参考方案1】:

使用简单的正则表达式修改 html 内容存在许多问题。

这是一种使用linkifyjs 模块的方法,您需要npm install。请注意,输入被认为是纯文本,而输出是 HTML 文本。

import  Pipe, PipeTransform  from '@angular/core';
import linkifyStr from 'linkifyjs/string';

@Pipe(name: 'linkify')
export class LinkifyPipe implements PipeTransform 
  transform(str: string): string 
    return str ? linkifyStr(str, target: '_system') : str;
  

注意:如果您需要指定 target 属性,请添加例如。 target: '_system' 作为linkifyStr 的第二个参数。

【讨论】:

感谢这个伟大的图书馆,但在打字稿中不能包含'linkifyjs/string',我找不到任何打字稿支持图书馆 我认为如果我们使用Angular2,我们需要将结果绑定到innerHtml ```` ``` 您可以像这样导入库:var linkifyString = require('linkifyjs/string'); 并以相同的方式使用,无需任何打字稿支持。 起初它对我不起作用,我一直收到string_1.default is not a function 错误。最终我发现将 import 语句更改为 import * as linkifyString from 'linkifyjs/string'; 解决了这个问题!【参考方案2】:

好的,要制作管道,您将制作一个由

组成的管道组件
  import  Pipe, PipeTransform  from '@angular/core';



    @Pipe(name: 'linkify')
    export class LinkifyPipe implements PipeTransform 
      transform(link: string): string 
        return this.linkify(link);
      

      private linkify(plainText): string
        let replacedText;
        let replacePattern1;
        let replacePattern2;
        let replacePattern3;

        //URLs starting with http://, https://, or ftp://
        replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
        replacedText = plainText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>');

        //URLs starting with "www." (without // before it, or it'd re-link the ones done above).
        replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
        replacedText = replacedText.replace(replacePattern2, '$1<a href="http://$2" target="_blank">$2</a>');

        //Change email addresses to mailto:: links.
        replacePattern3 = /(([a-zA-Z0-9\-\_\.])+@[a-zA-Z\_]+?(\.[a-zA-Z]2,6)+)/gim;
        replacedText = replacedText.replace(replacePattern3, '<a href="mailto:$1">$1</a>');

        return replacedText;
       
    

然后像你一样导入这个指令,将它传递给

pipes: [LinkifyPipe]

并像这样插入

url | linkify

【讨论】:

它将“”作为字符串返回,不像 dom 元素那样工作。 ***.com/questions/3103962/… 有一个 javascript DOMParser 可以将 HTML 转换为 JavaScript。我最近遇到了这个确切的问题,你不能使用字符串来欺骗 dom 元素 我认为如果我们使用Angular2,我们需要将结果绑定到innerHtml ```` ``` 在 linkify() 函数的开头,添加:plainText = plainText.replace("&lt;", "&amp;lt;").replace("&gt;","&amp;gt;"); 以阻止控制台中的注入尝试和投诉。然后像 Amr 提到的那样使用绑定到 innerHTML【参考方案3】:

你应该这样使用这个管道:

<div [innerHtml]="note.title | linkify"></div>

【讨论】:

【参考方案4】:

你应该检查 angular-linky https://github.com/dzonatan/angular-linky

<span [innerHTML]="yourText | linky"></span>

【讨论】:

最适合 Angular。【参考方案5】:

我已经寻找解决方案,但无济于事。我需要扩展处理 Angular 路由 [routerLink] 和使用 [innerHTML] 的外部链接的要求,而不需要 3rd 方库。

我的解决方案(总结):

Angular 2、Angular 5 - 用户点击事件/事件处理动态 [innerHTML] 生成的内容,使用管道和指令生成纯文本并将其转换为点击 URL,例如 #hashtags、@Handle、@Mention、#routerLink #href 和#mailto 等

Plunker 演示: https://embed.plnkr.co/68lZFY/

应用组件

import  Component, NgModule, VERSION from '@angular/core';
import  BrowserModule from '@angular/platform-browser';

@Component(
    selector: 'my-app',
    template: `<h1>Angular - Dynamic content click event</h1>
                        <p>Angular 2, Angular 5, Typescript - User click events/event handling for dynamic [innerHTML] generated content using pipe and directive to generate and converting plain text to click urls e.g #hashtags,  @Handle, @Mention, #routerLink #href and #mailto etc</p>
                        <ul>
                            <li *ngFor="let item of theList; let $index=index;" [innerHTML]="item | parseUrl" [dynamicContent]="currentView"></li>
                        <ul>`
)
export class AppComponent 
     theList:Array;

        constructor() 
                this.theList = [
                    'Lorem ipsum dolor sit amet, consectetur @adet dolore magna aliqua. Ut enim ad minim veniam',
                    'Lorem ipsum dolor sit amet, consectetur adipiscing http://google.com sed do eiusmod tempor #incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam',
                    'Lorem http://google.com ipsum dolor #sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt gna aliqua. Ut enim ad minim veniam',
                    'Lorem ipsum @dolor sit amet, consectetur @adipiscing elit, sed do eiusmod @tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam',
                    'Lorem ipsum dolor sit amet, smod tempor incididunt #ut labore et dolore @magna #aliqua. Ut enim ad minim veniam',
                    'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam',
                    'Lorem ipsum @dolor sit amet, #consectetur adipiscing elit, sed do eiusmod tempor http://google.com enim ad minim veniam'
                ];
        


指令

import  Directive, ElementRef, HostListener, Input  from '@angular/core';

@Directive(
    selector: '[dynamicContent]'
)
export class DynamicContent 

    constructor(private el: ElementRef)  

    @Input('dynamicContent') dynamicContent: string;

    @HostListener('click', ['$event']) onClick(e) 

        if (e.target.classList.contains('handle-link')) 
            let link: string = e.target.innerHTML;

            event.preventDefault();
            event.stopPropagation();

            alert("/search/handle/" + link.trim());

            //this.router.navigateByUrl("/search/handle/" + link.trim(),  skipLocationChange: false );

         else if (e.target.classList.contains('hashtag-link')) 
            let link: string = e.target.innerHTML;

            event.preventDefault();
            event.stopPropagation();

             alert("/search/hashtag/" + link.trim());

            //this.router.navigateByUrl("/search/hashtag/" + link.trim(),  skipLocationChange: false ); 

        

    


管道

export class ParseUrl implements PipeTransform 

    urls: any = /(\b(https?|http|ftp|ftps|Https|rtsp|Rtsp):\/\/[A-Z0-9+&@#\/%?=~_|!:,.;-]*[-A-Z0-9+&@#\/%=~_|])/gim; // Find/Replace URL's in text  
    hashtags: any = /(^|\s)(#[a-z\d][\w-]*)/ig; // Find/Replace #hashtags in text   
    mentions: any = /(^|\s)(@[a-z\d][\w-]*)/ig; // Find/Replace @Handle/Mentions in text    
    emails: any = /(\S+@\S+\.\S+)/gim; // Find/Replace email addresses in text

    transform(text: string) 
        return this.parseUrl(text);
    

    private parseUrl(text: string) 
        // Find/Replace URL's in text
        if (text.match(this.urls)) 
                text = text.replace(this.urls, function replacer($1, $2, $3) 
                        let url: any = $1;
                        let urlClean: any = url.replace("" + $3 + "://", "");

                        return "<a href=\"" + url + "\" target=\"_blank\">" + urlClean + "</a>";
                );
        

        // Find/Replace @Handle/Mentions in text
        if (text.match(this.hashtags)) 
            text = text.replace(this.hashtags, "<a href=\"/search/hashtag/$2\" class=\"hashtag-link\">$1$2</a>");
        

        // Find/Replace #hashtags in text
        if (text.match(this.mentions)) 
            text = text.replace(this.mentions, "<a href=\"/search/handle/$2\" class=\"handle-link\">$1$2</a>");
        

        // Find/Replace email addresses in text
        if (text.match(this.emails)) 
                text = text.replace(this.emails, "<a href=\"mailto:$1\">$1</a>");
        

        return text;
      

【讨论】:

【参考方案6】:

好的,我就是这样做的,留下答案希望对其他人有所帮助:

所以我正在使用一个函数来链接我的纯文本

private linkify(plainText): string
    let replacedText;
    let replacePattern1;
    let replacePattern2;
    let replacePattern3;

    //URLs starting with http://, https://, or ftp://
    replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim;
    replacedText = plainText.replace(replacePattern1, '<a href="$1" target="_blank">$1</a>');

    //URLs starting with "www." (without // before it, or it'd re-link the ones done above).
    replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
    replacedText = replacedText.replace(replacePattern2, '$1<a href="http://$2" target="_blank">$2</a>');

    //Change email addresses to mailto:: links.
    replacePattern3 = /(([a-zA-Z0-9\-\_\.])+@[a-zA-Z\_]+?(\.[a-zA-Z]2,6)+)/gim;
    replacedText = replacedText.replace(replacePattern3, '<a href="mailto:$1">$1</a>');

    return replacedText;

但这会返回一个带有 html 编码的字符串,所以如果我使用 &lt;p&gt;example&lt;/p&gt; 它将返回完整的编码(包括锚标签和 html)。

所以现在我使用 angular2 内置的 html 绑定:

这给了我解决方案

【讨论】:

有一些方法可以在渲染后动态注入可观察的 DOM 元素,但它不安全且繁重。你最好的选择是使用管道。我知道它们可能很可怕,但是您在插值上使用管道,它会操纵它并按照您的意愿将其吐出。如果您对此感兴趣,请告诉我,我会在答案框中写下一个示例,我们可以解决这个问题。 函数和管道本质上是一样的。然而,管道将是模块化和更清洁的 嘿@MarkAcosta,如果您想将其作为您的回答,欢迎您的回答,我可以在其工作后接受您的回答

以上是关于Angular2将纯文本转换为url的方式(锚链接)的主要内容,如果未能解决你的问题,请参考以下文章

使用 GET 指定 POST 的输入按钮/锚链接提交表单

使用 <base> 时使锚链接指向当前页面

将旧锚链接重定向到新锚链接

如何更改锚链接仅文本的颜色?

PHP将纯文本转换为标签链接

powershell 将纯文本字符串转换为安全字符串