nodebb-plugin-link-preview 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/library.js CHANGED
@@ -4,9 +4,12 @@ const winston = require.main.require('winston');
4
4
  const dns = require('dns');
5
5
 
6
6
  const { getLinkPreview } = require('link-preview-js');
7
+ const { load } = require('cheerio');
7
8
 
8
9
  const meta = require.main.require('./src/meta');
9
10
  const cache = require.main.require('./src/cache');
11
+ const posts = require.main.require('./src/posts');
12
+ const postsCache = require.main.require('./src/posts/cache');
10
13
 
11
14
  const controllers = require('./lib/controllers');
12
15
 
@@ -34,31 +37,30 @@ plugin.applyDefaults = async (data) => {
34
37
  return data;
35
38
  };
36
39
 
37
- async function process(content) {
38
- const anchorRegex = /<a\s+(?:[^>]*?\s+)?href=["']([^"']*)["'][^>]*>(.*?)<\/a>/g;
39
- const matches = [];
40
- let match;
41
-
40
+ async function process(content, opts) {
42
41
  const { embedHtml, embedImage, embedAudio, embedVideo } = await meta.settings.get('link-preview');
43
42
  if (![embedHtml, embedImage, embedAudio, embedVideo].some(prop => prop === 'on')) {
44
43
  return content;
45
44
  }
46
45
 
47
- // eslint-disable-next-line no-cond-assign
48
- while ((match = anchorRegex.exec(content)) !== null) {
49
- matches.push(match);
50
- }
46
+ const $ = load(content, null, false);
47
+ for (const anchor of $('a')) {
48
+ const $anchor = $(anchor);
49
+ const url = $anchor.attr('href');
51
50
 
52
- const previews = await Promise.all(matches.map(async (match) => {
53
- const anchor = match[1];
51
+ if ($anchor.hasClass('plugin-mentions-a')) {
52
+ break;
53
+ }
54
54
 
55
- const cached = cache.get(`link-preview:${anchor}`);
55
+ const cached = cache.get(`link-preview:${url}`);
56
56
  if (cached) {
57
- return await render(cached);
57
+ // eslint-disable-next-line no-await-in-loop
58
+ $anchor.replaceWith($(await render(cached)));
59
+ break;
58
60
  }
59
61
 
60
62
  // Generate the preview, but return false for now so as to not block response
61
- getLinkPreview(anchor, {
63
+ getLinkPreview(url, {
62
64
  resolveDNSHost: async url => new Promise((resolve, reject) => {
63
65
  const { hostname } = new URL(url);
64
66
  dns.lookup(hostname, (err, address) => {
@@ -84,34 +86,23 @@ async function process(content) {
84
86
 
85
87
  return false;
86
88
  },
87
- }).then((preview) => {
88
- const parsedUrl = new URL(anchor);
89
+ }).then(async (preview) => {
90
+ const parsedUrl = new URL(url);
89
91
  preview.hostname = parsedUrl.hostname;
90
92
 
91
93
  winston.verbose(`[link-preview] ${preview.url} (${preview.contentType}, cache: miss)`);
92
- cache.set(`link-preview:${anchor}`, preview);
94
+ cache.set(`link-preview:${url}`, preview);
95
+
96
+ if (opts.hasOwnProperty('pid') && await posts.exists(opts.pid)) {
97
+ postsCache.del(String(opts.pid));
98
+ }
93
99
  }).catch(() => {
94
- winston.verbose(`[link-preview] ${anchor} (invalid, cache: miss)`);
95
- cache.set(`link-preview:${anchor}`, {
96
- url: anchor,
97
- });
100
+ winston.verbose(`[link-preview] ${url} (invalid, cache: miss)`);
101
+ cache.set(`link-preview:${url}`, { url });
98
102
  });
103
+ }
99
104
 
100
- return false;
101
- }));
102
-
103
- // Replace match with embed
104
- previews.forEach((preview, idx) => {
105
- if (preview) {
106
- const match = matches[idx];
107
- const { index } = match;
108
- const { length } = match[0];
109
-
110
- content = `${content.substring(0, index)}${preview}${content.substring(index + length)}`;
111
- }
112
- });
113
-
114
- return content;
105
+ return $.html();
115
106
  }
116
107
 
117
108
  async function render(preview) {
@@ -145,9 +136,9 @@ async function render(preview) {
145
136
 
146
137
  plugin.onParse = async (payload) => {
147
138
  if (typeof payload === 'string') { // raw
148
- payload = await process(payload);
139
+ payload = await process(payload, {});
149
140
  } else if (payload && payload.postData && payload.postData.content) { // post
150
- payload.postData.content = await process(payload.postData.content);
141
+ payload.postData.content = await process(payload.postData.content, { pid: payload.postData.pid });
151
142
  }
152
143
 
153
144
  return payload;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-link-preview",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "A starter kit for quickly creating NodeBB plugins",
5
5
  "main": "library.js",
6
6
  "repository": {
@@ -43,6 +43,7 @@
43
43
  "lint-staged": "13.2.2"
44
44
  },
45
45
  "dependencies": {
46
+ "cheerio": "^1.0.0-rc.12",
46
47
  "link-preview-js": "^3.0.4"
47
48
  }
48
49
  }
@@ -1,8 +1,8 @@
1
- <div class="card col-6 position-relative link-preview">
1
+ <div class="card col-md-9 col-lg-6 position-relative link-preview">
2
2
  {{{ if images.length }}}
3
3
  {{{ each images }}}
4
4
  {{{ if @first }}}
5
- <img src="{@value}" class="card-img-top" style="max-height: 15rem;" />
5
+ <img src="{@value}" class="card-img-top not-responsive" style="max-height: 15rem;" />
6
6
  {{{ end }}}
7
7
  {{{ end }}}
8
8
  {{{ end }}}
@@ -18,7 +18,7 @@
18
18
  {{{ if favicons.length }}}
19
19
  {{{ each favicons }}}
20
20
  {{{ if @first }}}
21
- <img src="{@value}" alt="favicon" style="max-width: 21px; max-height: 21px;" />
21
+ <img src="{@value}" alt="favicon" class="not-responsive" style="max-width: 21px; max-height: 21px;" />
22
22
  {{{ end }}}
23
23
  {{{ end }}}
24
24
  {{{ end }}}