mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-12-20 07:20:27 +01:00
Compare commits
1 Commits
socket-not
...
link-previ
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
830d2a2de0 |
@@ -1,10 +1,14 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const nconf = require('nconf');
|
const nconf = require('nconf');
|
||||||
|
const fs = require('fs').promises;
|
||||||
|
const path = require('path');
|
||||||
const url = require('url');
|
const url = require('url');
|
||||||
|
const dns = require('dns');
|
||||||
const winston = require('winston');
|
const winston = require('winston');
|
||||||
const sanitize = require('sanitize-html');
|
const sanitize = require('sanitize-html');
|
||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
const { getLinkPreview } = require('link-preview-js');
|
||||||
|
|
||||||
const meta = require('../meta');
|
const meta = require('../meta');
|
||||||
const plugins = require('../plugins');
|
const plugins = require('../plugins');
|
||||||
@@ -129,13 +133,74 @@ module.exports = function (Posts) {
|
|||||||
sanitizeConfig = await plugins.hooks.fire('filter:sanitize.config', sanitizeConfig);
|
sanitizeConfig = await plugins.hooks.fire('filter:sanitize.config', sanitizeConfig);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Posts.processEmbeds = async (content) => {
|
||||||
|
const { app } = require('../webserver');
|
||||||
|
const anchorRegex = /<a\s+(?:[^>]*?\s+)?href=["']([^"']*)["'][^>]*>(.*?)<\/a>/g;
|
||||||
|
const matches = [];
|
||||||
|
let match;
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-cond-assign
|
||||||
|
while ((match = anchorRegex.exec(content)) !== null) {
|
||||||
|
matches.push(match);
|
||||||
|
}
|
||||||
|
|
||||||
|
const previews = await Promise.all(matches.map(async (match) => {
|
||||||
|
const anchor = match[1];
|
||||||
|
try {
|
||||||
|
const preview = await getLinkPreview(anchor, {
|
||||||
|
resolveDNSHost: async url => new Promise((resolve, reject) => {
|
||||||
|
const { hostname } = new URL(url);
|
||||||
|
dns.lookup(hostname, (err, address) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(address); // if address resolves to localhost or '127.0.0.1' library will throw an error
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (preview.contentType === 'text/html') {
|
||||||
|
console.log(preview);
|
||||||
|
return await app.renderAsync('partials/posts/embed', preview);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
console.log(previews);
|
||||||
|
|
||||||
|
// Replace match with embed
|
||||||
|
previews.forEach((preview, idx) => {
|
||||||
|
if (preview) {
|
||||||
|
const match = matches[idx];
|
||||||
|
const { index } = match;
|
||||||
|
const { length } = match[0];
|
||||||
|
|
||||||
|
content = `${content.substring(0, index)}${preview}${content.substring(index + length)}`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return content;
|
||||||
|
};
|
||||||
|
|
||||||
Posts.registerHooks = () => {
|
Posts.registerHooks = () => {
|
||||||
plugins.hooks.register('core', {
|
plugins.hooks.register('core', {
|
||||||
hook: 'filter:parse.post',
|
hook: 'filter:parse.post',
|
||||||
method: async (data) => {
|
method: [
|
||||||
data.postData.content = Posts.sanitize(data.postData.content);
|
async (data) => {
|
||||||
return data;
|
data.postData.content = Posts.sanitize(data.postData.content);
|
||||||
},
|
return data;
|
||||||
|
},
|
||||||
|
async (data) => {
|
||||||
|
console.log(data);
|
||||||
|
data.postData.content = await Posts.processEmbeds(data.postData.content);
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
plugins.hooks.register('core', {
|
plugins.hooks.register('core', {
|
||||||
|
|||||||
15
src/views/partials/posts/embed.tpl
Normal file
15
src/views/partials/posts/embed.tpl
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<div class="card col-6 position-relative">
|
||||||
|
{{{ if images.length }}}
|
||||||
|
{{{ each images }}}
|
||||||
|
{{{ if @first }}}
|
||||||
|
<img src="{@value}" class="card-img-top" />
|
||||||
|
{{{ end }}}
|
||||||
|
{{{ end }}}
|
||||||
|
{{{ end }}}
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">{title}</h5>
|
||||||
|
<p class="card-text">{description}</p>
|
||||||
|
<a href="{url}" class="stretched-link"></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user