Skip to content

Commit 8f07414

Browse files
committed
feat: unwrap t.co shortened links
1 parent 17719da commit 8f07414

5 files changed

Lines changed: 64 additions & 0 deletions

File tree

_locales/en/messages.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,12 @@
473473
"uninvertFollowButtonsLabel": {
474474
"message": "Uninvert Follow / Following buttons"
475475
},
476+
"unwrapTcoLinksLabel": {
477+
"message": "Unwrap t.co shortened links"
478+
},
479+
"unwrapTcoLinksInfo": {
480+
"message": "Replace t.co links with the actual destination URL"
481+
},
476482
"unmuteButtonText": {
477483
"message": "Unmute",
478484
"description": "Button used in the options page to unmute a muted Quote Tweet"

options.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,16 @@
283283
<span class="toggle"></span>
284284
</label>
285285
</section>
286+
<section class="checkbox">
287+
<label>
288+
<span id="unwrapTcoLinksLabel">Unwrap t.co shortened links</span>
289+
<input type="checkbox" name="unwrapTcoLinks">
290+
<span class="toggle"></span>
291+
</label>
292+
<p id="unwrapTcoLinksInfo">
293+
Replace t.co links with the actual destination URL
294+
</p>
295+
</section>
286296
<section class="checkbox">
287297
<label>
288298
<span id="restoreQuoteTweetsLinkLabel">Restore Quote Tweets link under Tweets</span>

options.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ for (let translationId of [
150150
'uiTweaksOptionsLabel',
151151
'unblurSensitiveContentLabel',
152152
'uninvertFollowButtonsLabel',
153+
'unwrapTcoLinksLabel',
154+
'unwrapTcoLinksInfo',
153155
'xFixesLabel',
154156
]) {
155157
let $el = document.getElementById(translationId)
@@ -267,6 +269,7 @@ const defaultConfig = {
267269
restoreOtherInteractionLinks: false,
268270
restoreQuoteTweetsLink: true,
269271
restoreTweetSource: true,
272+
unwrapTcoLinks: true,
270273
retweets: 'separate',
271274
showBlueReplyFollowersCount: false,
272275
showBlueReplyFollowersCountAmount: '1000000',

script.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ const config = {
185185
replaceLogo: true,
186186
restoreLinkHeadlines: true,
187187
restoreOtherInteractionLinks: false,
188+
unwrapTcoLinks: true,
188189
restoreQuoteTweetsLink: true,
189190
restoreTweetSource: true,
190191
retweets: 'separate',
@@ -5812,6 +5813,10 @@ function onTimelineChange($timeline, page, options = {}) {
58125813
if (!hideItem && config.restoreLinkHeadlines) {
58135814
restoreLinkHeadline($tweet)
58145815
}
5816+
5817+
if (!hideItem) {
5818+
unwrapTcoLinks($tweet)
5819+
}
58155820
}
58165821
else if (isOnNotificationsTimeline) {
58175822
/** @type {?import("./types").NotificationType} */
@@ -6046,6 +6051,10 @@ function onIndividualTweetTimelineChange($timeline, options) {
60466051
if (!hideItem && config.restoreLinkHeadlines) {
60476052
restoreLinkHeadline($tweet)
60486053
}
6054+
6055+
if (!hideItem) {
6056+
unwrapTcoLinks($tweet)
6057+
}
60496058
}
60506059
else {
60516060
let $article = $item.querySelector('article')
@@ -6513,6 +6522,41 @@ function restoreLinkHeadline($tweet) {
65136522
}
65146523
}
65156524

6525+
/**
6526+
* Unwraps t.co shortened links to show/use the actual destination URL.
6527+
* @param {HTMLElement} $tweet
6528+
*/
6529+
function unwrapTcoLinks($tweet) {
6530+
if (!config.unwrapTcoLinks) return
6531+
6532+
let $links = $tweet.querySelectorAll('a[href^="https://t.co/"]')
6533+
for (let $link of $links) {
6534+
if ($link.dataset.tcoUnwrapped) continue
6535+
6536+
let expandedUrl = null
6537+
let textContent = $link.textContent?.trim()
6538+
6539+
if (textContent) {
6540+
// Remove ellipsis that Twitter adds for truncation
6541+
textContent = textContent.replace(/$/, '').trim()
6542+
6543+
if (textContent.startsWith('http://') || textContent.startsWith('https://')) {
6544+
expandedUrl = textContent
6545+
} else if (textContent.includes('.') && !textContent.includes(' ')) {
6546+
expandedUrl = 'https://' + textContent
6547+
}
6548+
}
6549+
6550+
if (expandedUrl) {
6551+
$link.dataset.originalTco = $link.href
6552+
$link.href = expandedUrl
6553+
$link.dataset.tcoUnwrapped = 'true'
6554+
} else {
6555+
$link.dataset.tcoUnwrapped = 'attempted'
6556+
}
6557+
}
6558+
}
6559+
65166560
/**
65176561
* @param {HTMLElement} $focusedTweet
65186562
*/

types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ export type Config = {
7474
restoreLinkHeadlines: boolean
7575
restoreQuoteTweetsLink: boolean
7676
restoreOtherInteractionLinks: boolean
77+
unwrapTcoLinks: boolean
7778
restoreTweetSource: boolean
7879
retweets: SharedTweetsConfig
7980
showBlueReplyFollowersCount: boolean

0 commit comments

Comments
 (0)