Jelajahi Sumber

Add link_expansion route, with support for twitter embed; on frontend allow a string to be embedded via interpolation

sbkwgh 7 tahun lalu
induk
melakukan
3a9dab858f

+ 33 - 18
frontend/src/assets/js/linkExpander.js

@@ -40,6 +40,16 @@ export default {
 							content: data.description
 						}
 					}
+				},
+				'twitter': {
+					hostnameRegExp: /twitter\.com/,
+					pathnameRegExp: /\/.+\/status\/\d+/,
+					getURL (link) {
+						return '/api/v1/link_expansion/twitter?url=' + link.href;
+					},
+					getContent (link, data) {
+						return data.html;
+					}
 				}
 			};
 
@@ -85,25 +95,30 @@ export default {
 						.then(res => {
 							let content = expandPattern.getContent(link, res.data);
 							let h = document.createElement.bind(document);
-							
 							let div = h('div');
-							let h2 = h('h2');
-							let a = h('a');
-							let span = h('span');
-							let textNode = document.createTextNode(content.content);
-
-							a.textContent = content.title;
-							a.href = content.URL;
-							a.setAttribute('target', '_blank');
-							a.setAttribute('rel', 'noopener noreferrer');
-							span.textContent = 'from ' + link.hostname;
-
-							h2.appendChild(a);
-							h2.appendChild(span);
-							div.appendChild(h2)
-							div.appendChild(textNode)
-
-							div.classList.add('expanded_link');
+
+							if(typeof content === 'string') {
+								div.innerHTML = content;
+							} else {
+								let h2 = h('h2');
+								let a = h('a');
+								let span = h('span');
+								let textNode = document.createTextNode(content.content);
+
+								a.textContent = content.title;
+								a.href = content.URL;
+								a.setAttribute('target', '_blank');
+								a.setAttribute('rel', 'noopener noreferrer');
+								span.textContent = 'from ' + link.hostname;
+
+								h2.appendChild(a);
+								h2.appendChild(span);
+								div.appendChild(h2)
+								div.appendChild(textNode)
+
+								div.classList.add('expanded_link');
+							}
+
 							link.parentNode.replaceChild(div, link);
 
 							completedAPICall();

+ 11 - 0
frontend/src/assets/scss/elementStyles.scss

@@ -259,6 +259,17 @@ b, strong {
 	}
 }
 
+blockquote.twitter-tweet {
+	padding: 1rem;
+	padding-top: 0;
+	background-color: unset;
+	border: thick solid $color__gray--primary;
+
+	* {
+		padding: 0;
+	}
+}
+
 //Vue transition class
 .fade-enter-active, .fade-leave-active {
 	transition: opacity 0.2s;

+ 0 - 1
frontend/src/components/InputEditorPreview.vue

@@ -67,7 +67,6 @@
 		@at-root #{&}__markdownHTML {
 			height: 8.125rem;
 			overflow: auto;
-			word-break: break-word;
 			padding: 0.5rem;
 
 			@at-root #{&}--empty {

+ 0 - 1
frontend/src/components/routes/ThreadNew.vue

@@ -404,7 +404,6 @@
 
 			div.input_editor_preview__markdownHTML {
 				height: 14.1rem;
-				word-break: break-all;
 			}
 		}
 	}

+ 38 - 0
routes/link_expansion.js

@@ -0,0 +1,38 @@
+let https = require('https');
+let express = require('express');
+let router = express.Router();
+
+const Errors = require('../lib/errors.js');
+
+function getJsonHTTPS (url, cb) {
+	https.get(url, res => {
+		if(res.statusCode === 200) {
+			let chunks = [];
+
+			res.on('data', chunk => chunks.push(chunk));
+			res.on('end', () => {
+				let data = Buffer.concat(chunks).toString();
+				let json = JSON.parse(data);
+
+				cb(null, json);
+			})
+		} else {
+			cb(
+				new Error(`Request Failed.\nStatus Code: ${res.statusCode}`)
+			);
+		}
+	})
+}
+
+router.get('/twitter', async (req, res, next) => {
+	let url = 'https://publish.twitter.com/oembed?url=' + req.query.url
+	getJsonHTTPS(url, (err, data) => {
+		if(err) {
+			next(Errors.unknown);
+		} else {
+			res.json(data);
+		}
+	});
+});
+
+module.exports = router;

+ 1 - 0
server.js

@@ -49,6 +49,7 @@ app.use('/api/v1/ban', require('./routes/ban'))
 app.use('/api/v1/search', require('./routes/search'))
 app.use('/api/v1/log', require('./routes/log'))
 app.use('/api/v1/poll', require('./routes/poll'))
+app.use('/api/v1/link_expansion', require('./routes/link_expansion'))
 
 app.use('/static', express.static(path.join(__dirname, 'frontend', 'dist', 'static')))
 app.get('*', (req, res) => {