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|x)\.com\/([^/]+)\//)
71 if (m && !authorUsername) {
72 authorUsername = m[1]
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>