Autolink URLs in messages
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
d6be694d3b
commit
327290e971
3 changed files with 33 additions and 13 deletions
|
@ -19,12 +19,12 @@ const qa = s => document.querySelectorAll(s);
|
||||||
*/
|
*/
|
||||||
class ElemJS {
|
class ElemJS {
|
||||||
constructor(type) {
|
constructor(type) {
|
||||||
if (type instanceof HTMLElement) {
|
if (typeof type === "string") {
|
||||||
// If passed an existing element, bind to it
|
// Passed a tag name; create an element to bind to
|
||||||
this.bind(type);
|
|
||||||
} else {
|
|
||||||
// Otherwise, create a new detached element to bind to
|
|
||||||
this.bind(document.createElement(type));
|
this.bind(document.createElement(type));
|
||||||
|
} else {
|
||||||
|
// Passed an existing element; bind to it
|
||||||
|
this.bind(type);
|
||||||
}
|
}
|
||||||
this.children = [];
|
this.children = [];
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,9 +68,7 @@ function cleanHTML(html) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here we put all the processing of the messages that isn't as likely to potentially lead to security issues
|
// Here we put all the processing of the messages that isn't as likely to potentially lead to security issues
|
||||||
function postProcessElements(rootNode) {
|
function postProcessElements(element) {
|
||||||
const element = rootNode.element
|
|
||||||
|
|
||||||
element.querySelectorAll("pre").forEach(n => {
|
element.querySelectorAll("pre").forEach(n => {
|
||||||
new HighlightedCode(n)
|
new HighlightedCode(n)
|
||||||
})
|
})
|
||||||
|
@ -95,13 +93,11 @@ class HTMLMessage extends MatrixEvent {
|
||||||
this.clearChildren()
|
this.clearChildren()
|
||||||
|
|
||||||
let html = this.data.content.formatted_body
|
let html = this.data.content.formatted_body
|
||||||
const content = ejs("div")
|
|
||||||
|
|
||||||
const fragment = cleanHTML(html)
|
const fragment = cleanHTML(html)
|
||||||
content.element.appendChild(fragment)
|
postProcessElements(fragment)
|
||||||
postProcessElements(content)
|
|
||||||
|
|
||||||
this.child(content)
|
this.child(ejs(fragment))
|
||||||
|
|
||||||
super.render()
|
super.render()
|
||||||
}
|
}
|
||||||
|
@ -121,10 +117,33 @@ class HTMLMessage extends MatrixEvent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function autoLinkText(text) {
|
||||||
|
const fragment = ejs(new DocumentFragment())
|
||||||
|
let lastIndex = 0
|
||||||
|
text.replace(/https?:\/\/(?:[A-Za-z-]+\.)+[A-Za-z]{1,10}(?::[0-9]{1,6})?(?:\/[^ ]*)?/g, (url, index) => {
|
||||||
|
// add text before URL
|
||||||
|
fragment.addText(text.slice(lastIndex, index))
|
||||||
|
// add URL
|
||||||
|
fragment.child(
|
||||||
|
ejs("a")
|
||||||
|
.attribute("target", "_blank")
|
||||||
|
.attribute("noopener", "")
|
||||||
|
.attribute("href", url)
|
||||||
|
.addText(url)
|
||||||
|
)
|
||||||
|
// update state
|
||||||
|
lastIndex = index + url.length
|
||||||
|
})
|
||||||
|
// add final text
|
||||||
|
fragment.addText(text.slice(lastIndex))
|
||||||
|
return fragment
|
||||||
|
}
|
||||||
|
|
||||||
class TextMessage extends MatrixEvent {
|
class TextMessage extends MatrixEvent {
|
||||||
render() {
|
render() {
|
||||||
this.clearChildren()
|
this.clearChildren()
|
||||||
this.text(this.data.content.body)
|
const fragment = autoLinkText(this.data.content.body)
|
||||||
|
this.child(fragment)
|
||||||
super.render()
|
super.render()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
overflow-wrap: anywhere
|
overflow-wrap: anywhere
|
||||||
opacity: 1
|
opacity: 1
|
||||||
transition: opacity 0.2s ease-out
|
transition: opacity 0.2s ease-out
|
||||||
|
white-space: pre-wrap
|
||||||
|
|
||||||
&--pending
|
&--pending
|
||||||
opacity: 0.5
|
opacity: 0.5
|
||||||
|
|
Loading…
Reference in a new issue