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" target="_blank"></a>
51 </blockquote>
52 <script>
53 const params = {}
54 const searchParams = new URLSearchParams(window.location.search)
55 for (const [key, value] of searchParams.entries()) {
56 params[key] = value.replace(/\+/g, ' ')
57 }
58
59 const url = params['url']?.replace('x.com', 'twitter.com') || ''
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 const align = params['align']
64 const linkColor = params['link_color']
65 const theme = params['theme']
66 const conversation = params['conversation']
67 const cards = params['cards']
68 const lang = params['lang']
69
70 let authorUsername = (params['author_username'] ? params['author_username'] : '')
71 let formattedDate = 'Unknown date'
72
73 const m = url.match(/^(?:https?:)?\/\/(?:www\.)?twitter\.com\/([^/]+)\//)
74 if (m && !authorUsername) {
75 authorUsername = m[1]
76 }
77
78 if (authorUsername && authorUsername.substr(0, 1) !== '@') {
79 authorUsername = '@' + authorUsername
80 }
81
82 if (datetime) {
83 const d = new Date(datetime * 1000)
84 formattedDate = d.toDateString()
85 }
86
87 const t = document.getElementById('t')
88 if (align) {
89 t.align = align
90 }
91 if (linkColor) {
92 t.setAttribute('data-link-color', linkColor)
93 }
94 if (theme) {
95 t.setAttribute('data-theme', theme)
96 }
97 if (conversation) {
98 t.setAttribute('data-conversation', conversation)
99 }
100 if (cards) {
101 t.setAttribute('data-cards', cards)
102 }
103 if (lang) {
104 t.setAttribute('data-lang', lang)
105 }
106
107 if (authorName) {
108 document.getElementById('author_name').innerText = authorName
109 }
110 if (authorUsername) {
111 document.getElementById('author_username').innerText = authorUsername
112 }
113
114 document.getElementById('tweet').innerText = tweet
115
116 document.getElementById('date').href = url
117 document.getElementById('date').innerText = formattedDate
118
119 if (!params['force_fail']) {
120 const s = document.createElement('script')
121 s.src = 'https://platform.twitter.com/widgets.js'
122 document.body.appendChild(s)
123 }
124
125 let caller
126 const saveCaller = (e) => {
127 if (e.data.element) {
128 caller = e
129 sendResponse()
130 }
131 }
132
133 if (window.addEventListener) {
134 window.addEventListener('message', saveCaller, false)
135 } else {
136 window.attachEvent('onmessage', saveCaller)
137 }
138
139 let lastHeight = 0
140 const loadedTime = window.performance ? window.performance.now() : 0
141 const checkHeight = () => {
142 if (document.body.scrollHeight !== lastHeight && caller) {
143 lastHeight = document.body.scrollHeight
144 sendResponse()
145 }
146
147 /* give up after a while to save cpu */
148 if (window.performance && (window.performance.now() - loadedTime > (10 * 1000))) {
149 return
150 }
151
152 window.requestAnimationFrame(checkHeight)
153 }
154 window.requestAnimationFrame(checkHeight)
155
156 const sendResponse = () => {
157 if (caller.data.query === 'height') {
158 caller.source.postMessage(
159 {
160 element: caller.data.element,
161 height: document.body.scrollHeight + 20,
162 },
163 caller.origin,
164 )
165 }
166 }
167 </script>
168</body>
169</html>