nodebb-plugin-mentions 4.6.0 → 4.6.2

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.
Files changed (2) hide show
  1. package/library.js +44 -34
  2. package/package.json +4 -6
package/library.js CHANGED
@@ -5,7 +5,6 @@
5
5
  const _ = require('lodash');
6
6
  const validator = require('validator');
7
7
  const entitiesDecode = require('html-entities').decode;
8
- const cheerio = require('cheerio');
9
8
 
10
9
  const nconf = require.main.require('nconf');
11
10
  const winston = require.main.require('winston');
@@ -37,6 +36,7 @@ const parts = {
37
36
  };
38
37
  const regex = RegExp(`${parts.before}${parts.main}`, 'gu');
39
38
  const isLatinMention = /@[\w\d\-_.@]+$/;
39
+ const anchorRegex = /<a.*?href=['"](.+?)['"].*?>(.*?)<\/a>/ig;
40
40
 
41
41
  const Mentions = module.exports;
42
42
 
@@ -356,31 +356,36 @@ async function getMatches(content, isMarkdown = false) {
356
356
  }
357
357
  });
358
358
 
359
- const $ = cheerio.load(splitContent.join(''));
360
- const anchors = $('a');
361
- const urls = new Set();
362
- Array.from(anchors).forEach((anchor) => {
363
- const text = $(anchor).prop('innerText');
364
- const match = text.match(regex);
365
- if (match) {
366
- urls.add($(anchor).attr('href'));
367
- }
368
- });
359
+ // Early return
360
+ if (isMarkdown) {
361
+ return { splitContent, matches, urlMap: new Map() };
362
+ }
369
363
 
370
- // Filter out urls that don't backreference to a remote id
371
- const backrefs = await db.getObjectFields('remoteUrl:uid', Array.from(urls));
372
- const urlAsIdExists = await db.isSortedSetMembers('usersRemote:lastCrawled', Array.from(urls));
364
+ // Find matches via backreferenced href
365
+ const joined = splitContent.join('');
366
+ const anchors = new Set(joined.matchAll(anchorRegex));
373
367
  const urlMap = new Map();
374
- Array.from(urls).map(async (url, index) => {
375
- if (backrefs[url] || urlAsIdExists[index]) {
376
- urlMap.set(url, backrefs[url] || url);
377
- }
378
- });
379
- let slugs = await User.getUsersFields(Array.from(urlMap.values()), ['userslug']);
380
- slugs = slugs.map(({ userslug }) => userslug);
381
- Array.from(urlMap.keys()).forEach((url, idx) => {
382
- urlMap.set(url, `/user/${encodeURIComponent(slugs[idx])}`);
383
- });
368
+ const urls = new Set();
369
+ if (!isMarkdown && anchors.size) {
370
+ anchors.forEach((match) => {
371
+ const [, url] = match;
372
+ urls.add(url);
373
+ });
374
+
375
+ // Filter out urls that don't backreference to a remote id
376
+ const backrefs = urls.size ? await db.getObjectFields('remoteUrl:uid', Array.from(urls)) : {};
377
+ const urlAsIdExists = await db.isSortedSetMembers('usersRemote:lastCrawled', Array.from(urls));
378
+ Array.from(urls).map(async (url, index) => {
379
+ if (backrefs[url] || urlAsIdExists[index]) {
380
+ urlMap.set(url, backrefs[url] || url);
381
+ }
382
+ });
383
+ let slugs = await User.getUsersFields(Array.from(urlMap.values()), ['userslug']);
384
+ slugs = slugs.map(({ userslug }) => userslug);
385
+ Array.from(urlMap.keys()).forEach((url, idx) => {
386
+ urlMap.set(url, `/user/${encodeURIComponent(slugs[idx])}`);
387
+ });
388
+ }
384
389
 
385
390
  return { splitContent, matches, urlMap };
386
391
  }
@@ -497,20 +502,25 @@ Mentions.parseRaw = async (content, type = 'default') => {
497
502
  }
498
503
  }));
499
504
 
500
- const parsed = splitContent.join('');
505
+ let parsed = splitContent.join('');
506
+
507
+ // Early return if no urls to modify
508
+ if (!urlMap.size) {
509
+ return parsed;
510
+ }
501
511
 
502
512
  // Modify existing anchors to local profile
503
- const $ = cheerio.load(parsed);
504
- const anchors = $('a');
505
- Array.from(anchors).forEach((anchor) => {
506
- const $anchor = $(anchor);
507
- const url = $anchor.attr('href');
508
- if (urlMap.has(url)) {
509
- $anchor.attr('href', urlMap.get(url));
510
- }
513
+ const anchors = new Set(Array.from(parsed.matchAll(anchorRegex)).reverse());
514
+ if (!anchors.size) {
515
+ return parsed;
516
+ }
517
+
518
+ anchors.forEach(([match, href]) => {
519
+ const replacement = match.replace(href, urlMap.get(href));
520
+ parsed = parsed.split(match).join(replacement);
511
521
  });
512
522
 
513
- return $.html();
523
+ return parsed;
514
524
  };
515
525
 
516
526
  Mentions.clean = function (input, isMarkdown, stripBlockquote, stripCode) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-mentions",
3
- "version": "4.6.0",
3
+ "version": "4.6.2",
4
4
  "description": "NodeBB Plugin that allows users to mention other users by prepending an '@' sign to their username",
5
5
  "main": "library.js",
6
6
  "repository": {
@@ -22,16 +22,14 @@
22
22
  "compatibility": "^4.0.0"
23
23
  },
24
24
  "dependencies": {
25
- "cheerio": "^1.0.0-rc.12",
26
25
  "html-entities": "^2.3.2",
27
26
  "lodash": "4.17.21",
28
- "sanitize-html": "^2.13.0",
29
27
  "validator": "^13.0.0"
30
28
  },
31
29
  "devDependencies": {
32
- "mocha": "10.4.0",
33
- "eslint": "9.3.0",
30
+ "eslint": "^8.0.0",
34
31
  "eslint-config-nodebb": "0.2.1",
35
- "eslint-plugin-import": "2.29.1"
32
+ "eslint-plugin-import": "2.29.1",
33
+ "mocha": "10.4.0"
36
34
  }
37
35
  }