Embed Tweets in an iframe - https://tf.rita.moe
1<!DOCTYPE html> 2<html lang="en"> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 <title>twitframe</title> 7 <meta name="description" content="Embed Tweets in an iframe" /> 8 <style> 9 body { 10 font-family: helvetica neue, arial, sans-serif; 11 padding-top: 1px; 12 } 13 14 #brand { 15 background-color: #fbfbfb; 16 color: #bbb; 17 font-size: 8pt; 18 left: 0px; 19 opacity: 0.2; 20 padding-left: 0.5rem; 21 padding-right: 0.5rem; 22 position: absolute; 23 top: 0px; 24 } 25 26 #brand a { 27 color: #aaa; 28 text-decoration: none; 29 } 30 31 blockquote.twitter-tweet { 32 margin: 1rem auto; 33 } 34 35 #author_name { 36 font-weight: bold; 37 } 38 </style> 39</head> 40<body> 41 <span id="brand"> 42 <a href="https://tf.rita.moe/?ref=t" target="_blank">twitframe</a> 43 </span> 44 <blockquote class="twitter-tweet" id="t"> 45 <span id="author_name"></span> 46 <span id="author_username"></span> 47 <p> 48 <span id="tweet"></span> 49 </p> 50 <a id="date"></a> 51 </blockquote> 52 <script> 53 const params = {} 54 window.location.search.slice(1).split('&').forEach((part) => { 55 const item = part.split('=') 56 params[item[0]] = decodeURIComponent(item[1]).replace(/\+/g, ' ') 57 }) 58 59 const url = params['url'] || '' 60 const datetime = (params['datetime'] || 0) 61 const tweet = (params['tweet'] ? params['tweet'] : 'Loading tweet...') 62 const authorName = (params['author_name'] ? params['author_name'] : '') 63 let authorUsername = (params['author_username'] ? params['author_username'] : '') 64 const align = params['align'] 65 const linkColor = params['link_color'] 66 const theme = params['theme'] 67 let formattedDate = 'Unknown date' 68 const conversation = params['conversation'] 69 70 const m = url.match(/^(https?:)?\/\/(www\.)?twitter\.com\/([^/]+)\//) 71 if (m && !authorUsername) { 72 authorUsername = m[3] 73 } 74 75 if (authorUsername && authorUsername.substr(0, 1) !== '@') { 76 authorUsername = '@' + authorUsername 77 } 78 79 if (datetime) { 80 const d = new Date(datetime * 1000) 81 formattedDate = d.toDateString() 82 } 83 84 const t = document.getElementById('t') 85 if (align) { 86 t.align = align 87 } 88 if (linkColor) { 89 t.setAttribute('data-link-color', linkColor) 90 } 91 if (theme) { 92 t.setAttribute('data-theme', theme) 93 } 94 if (conversation) { 95 t.setAttribute('data-conversation', conversation) 96 } 97 98 if (authorName) { 99 document.getElementById('author_name').innerText = authorName 100 } 101 if (authorUsername) { 102 document.getElementById('author_username').innerText = authorUsername 103 } 104 105 document.getElementById('tweet').innerText = tweet 106 107 document.getElementById('date').href = url 108 document.getElementById('date').innerText = formattedDate 109 110 if (!params['force_fail']) { 111 const s = document.createElement('script') 112 s.src = 'https://platform.twitter.com/widgets.js' 113 document.body.appendChild(s) 114 } 115 116 let caller 117 const saveCaller = (e) => { 118 if (e.data.element) { 119 caller = e 120 sendResponse() 121 } 122 } 123 124 if (window.addEventListener) { 125 window.addEventListener('message', saveCaller, false) 126 } else { 127 window.attachEvent('onmessage', saveCaller) 128 } 129 130 let lastHeight = 0 131 const loadedTime = window.performance ? window.performance.now() : 0 132 const checkHeight = () => { 133 if (document.body.scrollHeight !== lastHeight && caller) { 134 lastHeight = document.body.scrollHeight 135 sendResponse() 136 } 137 138 /* give up after a while to save cpu */ 139 if (window.performance && (window.performance.now() - loadedTime > (10 * 1000))) { 140 return 141 } 142 143 window.requestAnimationFrame(checkHeight) 144 } 145 window.requestAnimationFrame(checkHeight) 146 147 const sendResponse = () => { 148 if (caller.data.query === 'height') { 149 caller.source.postMessage( 150 { 151 element: caller.data.element, 152 height: document.body.scrollHeight + 20, 153 }, 154 caller.origin, 155 ) 156 } 157 } 158 </script> 159</body> 160</html>