Skip to content

Commit 5716343

Browse files
committed
Use the href of links for link previews, not node.textContent
Until now we used node.textContent to determine whether a paragraph is a link that warrants a link preview. Instead, we now check whether the paragraph has a single text node wich is a link and use its href. Text nodes with empty textContent are ignored in order to allow whitespaces before and after the link. This way we ensure to always show the preview of the link target, not of the description text. Both may differ, which has security implications. Also, links with a custom description get a link preview as well. And last but not least, it fixes link previes for URLs with spaces. (Background: for some reason, url-encoded spaces in textContent of links get decoded when they're transformed to markdown and written to a file. Therefore URLs with spaces lost their link preview once the Text session was closed prior to this commit) Fixes: #3871 Signed-off-by: Jonas <[email protected]>
1 parent b6d08ad commit 5716343

File tree

1 file changed

+37
-6
lines changed

1 file changed

+37
-6
lines changed

src/nodes/ParagraphView.vue

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,51 @@ export default {
6363
},
6464
beforeCreate() {
6565
this.debouncedUpdateText = debounce((newNode) => {
66-
this.text = this.getTextReference(this.node?.textContent)
66+
this.text = this.getTextReference(this.node)
6767
}, 500)
6868
},
6969
created() {
70-
this.text = this.getTextReference(this.node?.textContent)
70+
this.text = this.getTextReference(this.node)
7171
},
7272
beforeUnmount() {
7373
this.debouncedUpdateText?.cancel()
7474
},
7575
methods: {
76-
getTextReference(text) {
77-
const PATTERN = /(^)(https?:\/\/)?((?:[-A-Z0-9+_]+\.)+[-A-Z]+(?:\/[-A-Z0-9+&@#%?=~_|!:,.;()]*)*)($)/ig
78-
if ((new RegExp(PATTERN)).test(text)) {
79-
return text
76+
getTextReference(node) {
77+
if (!node?.childCount) {
78+
return null
79+
}
80+
81+
// Only regard paragraphs with exactly one text node (ignoring whitespace-only nodes)
82+
let textNode
83+
for (let i = 0; i < node.childCount; i++) {
84+
const childNode = node.child(i)
85+
86+
// Disregard paragraphs with non-text nodes
87+
if (childNode.type.name !== 'text') {
88+
return null
89+
}
90+
91+
// Ignore children with empty text
92+
if (!childNode.textContent.trim()) {
93+
continue
94+
}
95+
96+
// Disregard paragraphs with more than one text nodes
97+
if (textNode) {
98+
return null
99+
}
100+
101+
textNode = childNode
102+
}
103+
104+
// Check if the text node is a link
105+
const linkMark = textNode?.marks.find((m) => m.type.name === 'link')
106+
const href = linkMark?.attrs?.href
107+
108+
const PATTERN = /(^)(https?:\/\/)((?:[-A-Z0-9+_]+\.)+[-A-Z]+(?:\/[-A-Z0-9+&@#%?=~_|!:,.;()]*)*)($)/ig
109+
if ((new RegExp(PATTERN)).test(href)) {
110+
return href
80111
}
81112
82113
return null

0 commit comments

Comments
 (0)