New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(viewer): recognise URLs in text value and convert into link (DSP-1595) #315
Changes from 4 commits
c2631ed
e27c9bf
8eeb1f7
3b5b747
29c25eb
ab088df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { LinkifyPipe } from './linkify.pipe'; | ||
|
||
describe('LinkifyPipe', () => { | ||
|
||
let pipe: LinkifyPipe; | ||
|
||
beforeEach(() => { | ||
pipe = new LinkifyPipe(); | ||
}); | ||
|
||
it('create an instance', () => { | ||
expect(pipe).toBeTruthy(); | ||
}); | ||
|
||
it('should recognize the url without protocol but with hashtag at the end', () => { | ||
const text = 'You can visit the app on app.dasch.swiss/#'; | ||
const linkifiedSnippet = pipe.transform(text); | ||
expect(linkifiedSnippet).toEqual('You can visit the app on <a href="http://app.dasch.swiss/#" target="_blank">app.dasch.swiss/#</a>'); | ||
}); | ||
|
||
it('should recognize the url with protocol followed by full stop', () => { | ||
const text = 'You can visit the app on https://app.dasch.swiss.'; | ||
const linkifiedSnippet = pipe.transform(text); | ||
expect(linkifiedSnippet).toEqual('You can visit the app on <a href="https://app.dasch.swiss" target="_blank">https://app.dasch.swiss</a>.'); | ||
}); | ||
|
||
it('should recognize both urls in the example text', () => { | ||
const text = 'You can visit the app on https://app.dasch.swiss and the documentation on docs.dasch.swiss.'; | ||
const linkifiedSnippet = pipe.transform(text); | ||
expect(linkifiedSnippet).toEqual('You can visit the app on <a href="https://app.dasch.swiss" target="_blank">https://app.dasch.swiss</a> and the documentation on <a href="http://docs.dasch.swiss" target="_blank">docs.dasch.swiss</a>.'); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { Pipe, PipeTransform } from '@angular/core'; | ||
|
||
/** | ||
* This pipe analyses a string and converts any url into a href tags | ||
*/ | ||
@Pipe({ | ||
name: 'dspLinkify' | ||
}) | ||
export class LinkifyPipe implements PipeTransform { | ||
|
||
// constructor(private _domSanitizer: DomSanitizer) { } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can this be removed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. removed in 29c25eb |
||
|
||
transform(value: string): string { | ||
let stylizedText: string = ''; | ||
if (value && value.length > 0) { | ||
for (let str of value.split(' ')) { | ||
// if string/url ends with a full stop '.' or column ':' the pipe will not recognize the url | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment should be updated to align with line 19. Also, ':' is called a colon in english :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh yes... colon, not column fixed in 29c25eb There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and in ab088df |
||
const lastChar = str.substring(str.length - 1); | ||
const endsWithFullStop = (lastChar === '.' || lastChar === ':' || lastChar === ',' || lastChar === ';'); | ||
let end = ' '; | ||
if (endsWithFullStop) { | ||
str = str.slice(0, -1); | ||
end = '.' | ||
} | ||
if (this._recognizeUrl(str)) { | ||
const url = this._setProtocol(str); | ||
stylizedText += `<a href="${url}" target="_blank">${str}</a>${end}`; | ||
} else { | ||
stylizedText += str + end; | ||
} | ||
} | ||
return stylizedText.trim(); | ||
} else { | ||
return value; | ||
} | ||
} | ||
|
||
private _recognizeUrl(str: string): boolean { | ||
const pattern = new RegExp( | ||
'^(https?:\\/\\/)?' + // protocol | ||
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name | ||
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address | ||
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path | ||
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string | ||
'(\\#[-a-z\\d_]*)?$', | ||
'i' | ||
); // fragment locator | ||
return pattern.test(str); | ||
} | ||
|
||
private _setProtocol(url: string): string { | ||
if (!/^(?:f|ht)tps?\:\/\//.test(url)) { | ||
url = 'http://' + url; | ||
} | ||
return url; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
<div [innerHTML]="htmlFromKnora" class="value"></div> | ||
<div [innerHTML]="htmlFromKnora | dspLinkify" class="value"></div> | ||
<div *ngIf="comment"> | ||
<label>{{commentLabel}}: </label><span class="comment">{{comment}}</span> | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tags -> tag
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in 29c25eb