nodebb-plugin-mentions 4.5.3 → 4.6.1

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 (45) hide show
  1. package/.eslintrc +2 -2
  2. package/LICENSE +7 -7
  3. package/README.md +13 -13
  4. package/languages/ar/notifications.json +2 -2
  5. package/languages/bg/notifications.json +2 -2
  6. package/languages/bn/notifications.json +2 -2
  7. package/languages/da/notifications.json +2 -2
  8. package/languages/de/notifications.json +5 -5
  9. package/languages/el/notifications.json +2 -2
  10. package/languages/en@pirate/notifications.json +4 -4
  11. package/languages/en_GB/mentions.json +3 -3
  12. package/languages/en_GB/notifications.json +7 -7
  13. package/languages/en_US/notifications.json +4 -4
  14. package/languages/es/notifications.json +3 -3
  15. package/languages/et/notifications.json +2 -2
  16. package/languages/fa_IR/notifications.json +4 -4
  17. package/languages/fi/notifications.json +2 -2
  18. package/languages/fr/notifications.json +5 -5
  19. package/languages/gl/notifications.json +2 -2
  20. package/languages/id/notifications.json +2 -2
  21. package/languages/it/notifications.json +3 -3
  22. package/languages/ja/notifications.json +4 -4
  23. package/languages/jbo/notifications.json +4 -4
  24. package/languages/ko/notifications.json +2 -2
  25. package/languages/lt/notifications.json +2 -2
  26. package/languages/ms/notifications.json +2 -2
  27. package/languages/nl/notifications.json +2 -2
  28. package/languages/pl/mentions.json +3 -3
  29. package/languages/pl/notifications.json +6 -6
  30. package/languages/pt-PT/notifications.json +6 -6
  31. package/languages/pt_BR/notifications.json +3 -3
  32. package/languages/ro/notifications.json +2 -2
  33. package/languages/rw/notifications.json +2 -2
  34. package/languages/sl/notifications.json +2 -2
  35. package/languages/sr/notifications.json +2 -2
  36. package/languages/sv/notifications.json +2 -2
  37. package/languages/tr/notifications.json +6 -6
  38. package/languages/vi/notifications.json +2 -2
  39. package/languages/zh-CN/mentions.json +3 -3
  40. package/languages/zh-CN/notifications.json +5 -5
  41. package/languages/zh_TW/notifications.json +2 -2
  42. package/library.js +67 -13
  43. package/package.json +4 -2
  44. package/plugin.json +31 -31
  45. package/static/.eslintrc +3 -3
package/.eslintrc CHANGED
@@ -1,3 +1,3 @@
1
- {
2
- "extends": "nodebb/lib"
1
+ {
2
+ "extends": "nodebb/lib"
3
3
  }
package/LICENSE CHANGED
@@ -1,8 +1,8 @@
1
- Copyright (c) 2013-2014, Julian Lam <julian@designcreateplay.com>
2
- All rights reserved.
3
-
4
- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5
-
6
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
1
+ Copyright (c) 2013-2014, Julian Lam <julian@designcreateplay.com>
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5
+
6
+ Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7
+ Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8
8
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/README.md CHANGED
@@ -1,14 +1,14 @@
1
- # Username/Group Mentions
2
-
3
- This NodeBB plugin allows posters to reference (or *mention*) other users or groups on a NodeBB by simply
4
- precluding the `@` symbol before a username.
5
-
6
- A link is automatically added to the post.
7
-
8
- ## Installation
9
-
10
- This plugin is bundled with every NodeBB install. If not, you can install it via the Plugins page of the ACP.
11
-
12
- Alternatively,
13
-
1
+ # Username/Group Mentions
2
+
3
+ This NodeBB plugin allows posters to reference (or *mention*) other users or groups on a NodeBB by simply
4
+ precluding the `@` symbol before a username.
5
+
6
+ A link is automatically added to the post.
7
+
8
+ ## Installation
9
+
10
+ This plugin is bundled with every NodeBB install. If not, you can install it via the Plugins page of the ACP.
11
+
12
+ Alternatively,
13
+
14
14
  npm install nodebb-plugin-mentions
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> ذكرَ اسمك في <strong>%2</strong>"
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> ذكرَ اسمك في <strong>%2</strong>"
3
3
  }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> Ви спомена в <strong>%2</strong>"
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> Ви спомена в <strong>%2</strong>"
3
3
  }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong>, <strong>%2</strong> এ আপনার নাম উল্লেখ করেছেন"
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong>, <strong>%2</strong> এ আপনার নাম উল্লেখ করেছেন"
3
3
  }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> nævnte dig i <strong>%2</strong>"
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> nævnte dig i <strong>%2</strong>"
3
3
  }
@@ -1,6 +1,6 @@
1
- {
2
- "mentions": "Erwähnungen",
3
- "user-mentioned-you-in": "<strong>%1</strong> erwähnte dich in <strong>%2</strong>",
4
- "user-mentioned-group-in": "<strong>%1</strong> erwähnte <strong>%2</strong> in <strong>%3</strong>",
5
- "notificationType_mention": "Wenn dich jemand erwähnt"
1
+ {
2
+ "mentions": "Erwähnungen",
3
+ "user-mentioned-you-in": "<strong>%1</strong> erwähnte dich in <strong>%2</strong>",
4
+ "user-mentioned-group-in": "<strong>%1</strong> erwähnte <strong>%2</strong> in <strong>%3</strong>",
5
+ "notificationType_mention": "Wenn dich jemand erwähnt"
6
6
  }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "Ο/Η <strong>%1</strong> σε ανέφερε στο <strong>%2</strong>"
1
+ {
2
+ "user-mentioned-you-in": "Ο/Η <strong>%1</strong> σε ανέφερε στο <strong>%2</strong>"
3
3
  }
@@ -1,4 +1,4 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> spoke yer name in <strong>%2</strong>",
3
- "user-mentioned-group-in": "<strong>%1</strong> called fer <strong>%2</strong> in <strong>%3</strong>"
4
- }
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> spoke yer name in <strong>%2</strong>",
3
+ "user-mentioned-group-in": "<strong>%1</strong> called fer <strong>%2</strong> in <strong>%3</strong>"
4
+ }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> mentioned you in <strong>%2</strong>"
3
- }
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> mentioned you in <strong>%2</strong>"
3
+ }
@@ -1,7 +1,7 @@
1
- {
2
- "mentions": "Mentions",
3
- "user-mentioned-you-in": "<strong>%1</strong> mentioned you in <strong>%2</strong>",
4
- "user-mentioned-you-in-room": "<strong>%1</strong> mentioned you in <strong class=\"text-nowrap\"><i class=\"fa %2\"></i>%3</strong>",
5
- "user-mentioned-group-in": "<strong>%1</strong> mentioned <strong>%2</strong> in <strong>%3</strong>",
6
- "notificationType-mention": "When someone mentions you"
7
- }
1
+ {
2
+ "mentions": "Mentions",
3
+ "user-mentioned-you-in": "<strong>%1</strong> mentioned you in <strong>%2</strong>",
4
+ "user-mentioned-you-in-room": "<strong>%1</strong> mentioned you in <strong class=\"text-nowrap\"><i class=\"fa %2\"></i>%3</strong>",
5
+ "user-mentioned-group-in": "<strong>%1</strong> mentioned <strong>%2</strong> in <strong>%3</strong>",
6
+ "notificationType-mention": "When someone mentions you"
7
+ }
@@ -1,4 +1,4 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> mentioned you in <strong>%2</strong>",
3
- "user-mentioned-group-in": "<strong>%1</strong> mentioned <strong>%2</strong> in <strong>%3</strong>"
4
- }
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> mentioned you in <strong>%2</strong>",
3
+ "user-mentioned-group-in": "<strong>%1</strong> mentioned <strong>%2</strong> in <strong>%3</strong>"
4
+ }
@@ -1,4 +1,4 @@
1
- {
2
- "mentions": "Menciones",
3
- "user-mentioned-you-in": "<strong>%1</strong> te mencionó en <strong>%2</strong>"
1
+ {
2
+ "mentions": "Menciones",
3
+ "user-mentioned-you-in": "<strong>%1</strong> te mencionó en <strong>%2</strong>"
4
4
  }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> mainis sind postituses <strong>%2</strong>"
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> mainis sind postituses <strong>%2</strong>"
3
3
  }
@@ -1,4 +1,4 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> شما رو در <strong>%2</strong> منشن کرده",
3
- "user-mentioned-group-in": "<strong>%1</strong> گروه <strong>%2</strong> رو در <strong>%3</strong> منشن کرده"
4
- }
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> شما رو در <strong>%2</strong> منشن کرده",
3
+ "user-mentioned-group-in": "<strong>%1</strong> گروه <strong>%2</strong> رو در <strong>%3</strong> منشن کرده"
4
+ }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> mainitsi sinut viestissä <strong>%2</strong>"
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> mainitsi sinut viestissä <strong>%2</strong>"
3
3
  }
@@ -1,6 +1,6 @@
1
- {
2
- "mentions": "Mentions",
3
- "user-mentioned-you-in": "<strong>%1</strong> vous a mentionné dans <strong>%2</strong>",
4
- "user-mentioned-group-in": "<strong>%1</strong> a mentionné <strong>%2</strong> dans <strong>%3</strong>",
5
- "notificationType_mention": "Lorsque quelqu'un vous mentionne"
1
+ {
2
+ "mentions": "Mentions",
3
+ "user-mentioned-you-in": "<strong>%1</strong> vous a mentionné dans <strong>%2</strong>",
4
+ "user-mentioned-group-in": "<strong>%1</strong> a mentionné <strong>%2</strong> dans <strong>%3</strong>",
5
+ "notificationType_mention": "Lorsque quelqu'un vous mentionne"
6
6
  }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> mencionóute en <strong>%2</strong>"
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> mencionóute en <strong>%2</strong>"
3
3
  }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> menyebut mu di <strong>%2</strong>"
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> menyebut mu di <strong>%2</strong>"
3
3
  }
@@ -1,4 +1,4 @@
1
- {
2
- "mentions": "Menzioni",
3
- "user-mentioned-you-in": "<strong>%1</strong> ti ha menzionato in <strong>%2</strong>"
1
+ {
2
+ "mentions": "Menzioni",
3
+ "user-mentioned-you-in": "<strong>%1</strong> ti ha menzionato in <strong>%2</strong>"
4
4
  }
@@ -1,5 +1,5 @@
1
- {
2
- "mentions": "メンション",
3
- "user-mentioned-you-in": "<strong>%1</strong> mentioned you in <strong>%2</strong>",
4
- "user-mentioned-group-in": "<strong>%1</strong> mentioned <strong>%2</strong> in <strong>%3</strong>"
1
+ {
2
+ "mentions": "メンション",
3
+ "user-mentioned-you-in": "<strong>%1</strong> mentioned you in <strong>%2</strong>",
4
+ "user-mentioned-group-in": "<strong>%1</strong> mentioned <strong>%2</strong> in <strong>%3</strong>"
5
5
  }
@@ -1,4 +1,4 @@
1
- {
2
- "user-mentioned-you-in": "la .<strong>%1</strong>. klacpe do la .<strong>%2</strong>.",
3
- "user-mentioned-group-in": "la .<strong>%1</strong>. klacpe la .<strong>%2</strong>. la .<strong>%3</strong>."
4
- }
1
+ {
2
+ "user-mentioned-you-in": "la .<strong>%1</strong>. klacpe do la .<strong>%2</strong>.",
3
+ "user-mentioned-group-in": "la .<strong>%1</strong>. klacpe la .<strong>%2</strong>. la .<strong>%3</strong>."
4
+ }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong>님이 <strong>%2</strong>에서 나를 언급했습니다."
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong>님이 <strong>%2</strong>에서 나를 언급했습니다."
3
3
  }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> paminėjo Jus <strong>%2</strong>"
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> paminėjo Jus <strong>%2</strong>"
3
3
  }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> sebut anda di <strong>%2</strong>"
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> sebut anda di <strong>%2</strong>"
3
3
  }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "Onze naam is genoemd door <strong>%1</strong> in <strong>%2</strong>."
1
+ {
2
+ "user-mentioned-you-in": "Onze naam is genoemd door <strong>%1</strong> in <strong>%2</strong>."
3
3
  }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> wspomniał o Tobie w <strong>%2</strong>"
3
- }
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> wspomniał o Tobie w <strong>%2</strong>"
3
+ }
@@ -1,6 +1,6 @@
1
- {
2
- "mentions": "Wspomnienia",
3
- "user-mentioned-you-in": "<strong>%1</strong> wspomniał o Tobie w <strong>%2</strong>",
4
- "user-mentioned-group-in": "<strong>%1</strong> wspomniał <strong>%2</strong> w <strong>%3</strong>",
5
- "notificationType_mention": "Kiedy ktoś o Tobie wspomni"
6
- }
1
+ {
2
+ "mentions": "Wspomnienia",
3
+ "user-mentioned-you-in": "<strong>%1</strong> wspomniał o Tobie w <strong>%2</strong>",
4
+ "user-mentioned-group-in": "<strong>%1</strong> wspomniał <strong>%2</strong> w <strong>%3</strong>",
5
+ "notificationType_mention": "Kiedy ktoś o Tobie wspomni"
6
+ }
@@ -1,6 +1,6 @@
1
- {
2
- "mentions": "Menções",
3
- "user-mentioned-you-in": "<strong>%1</strong> mencionou-te no tópico <strong>%2</strong>",
4
- "user-mentioned-group-in": "<strong>%1</strong> mencionou o grupo <strong>%2</strong> no tópico <strong>%3</strong>",
5
- "notificationType_mention": "Quando alguém te menciona"
6
- }
1
+ {
2
+ "mentions": "Menções",
3
+ "user-mentioned-you-in": "<strong>%1</strong> mencionou-te no tópico <strong>%2</strong>",
4
+ "user-mentioned-group-in": "<strong>%1</strong> mencionou o grupo <strong>%2</strong> no tópico <strong>%3</strong>",
5
+ "notificationType_mention": "Quando alguém te menciona"
6
+ }
@@ -1,4 +1,4 @@
1
- {
2
- "mentions": "Menções",
3
- "user-mentioned-you-in": "<strong>%1</strong> mencionou você em <strong>%2</strong>"
1
+ {
2
+ "mentions": "Menções",
3
+ "user-mentioned-you-in": "<strong>%1</strong> mencionou você em <strong>%2</strong>"
4
4
  }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> te-a menționat în <strong>%2</strong>"
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> te-a menționat în <strong>%2</strong>"
3
3
  }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> yakuvuze muri <strong>%2</strong>"
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> yakuvuze muri <strong>%2</strong>"
3
3
  }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> te je omenil v <strong>%2</strong>"
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> te je omenil v <strong>%2</strong>"
3
3
  }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> вас помену у <strong>%2</strong>"
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> вас помену у <strong>%2</strong>"
3
3
  }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> nämnde dig i <strong>%2</strong>"
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> nämnde dig i <strong>%2</strong>"
3
3
  }
@@ -1,6 +1,6 @@
1
- {
2
- "mentions": "Bahsedilmeler",
3
- "user-mentioned-you-in": "<strong>%1</strong> sizden şu konuda bahsetti: <strong>%2</strong>",
4
- "user-mentioned-group-in": "<strong>%1</strong> kullanıcısı <strong>%2</strong> grubundan şu konuda bahsetti: <strong>%3</strong>",
5
- "notificationType_mention": "Biri sizden bahsettiğinde"
6
- }
1
+ {
2
+ "mentions": "Bahsedilmeler",
3
+ "user-mentioned-you-in": "<strong>%1</strong> sizden şu konuda bahsetti: <strong>%2</strong>",
4
+ "user-mentioned-group-in": "<strong>%1</strong> kullanıcısı <strong>%2</strong> grubundan şu konuda bahsetti: <strong>%3</strong>",
5
+ "notificationType_mention": "Biri sizden bahsettiğinde"
6
+ }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> nhắc đến bạn trong <strong>%2</strong>"
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> nhắc đến bạn trong <strong>%2</strong>"
3
3
  }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> 在 <strong>%2</strong> 中提到了您"
3
- }
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> 在 <strong>%2</strong> 中提到了您"
3
+ }
@@ -1,6 +1,6 @@
1
- {
2
- "mentions": "提到",
3
- "user-mentioned-you-in": "<strong>%1</strong> 在 <strong>%2</strong> 中提到了你",
4
- "user-mentioned-group-in": "<strong>%1</strong> 在 <strong>%3</strong> 中提到了 <strong>%2</strong>",
5
- "notificationType_mention": "当有人提到你时"
1
+ {
2
+ "mentions": "提到",
3
+ "user-mentioned-you-in": "<strong>%1</strong> 在 <strong>%2</strong> 中提到了你",
4
+ "user-mentioned-group-in": "<strong>%1</strong> 在 <strong>%3</strong> 中提到了 <strong>%2</strong>",
5
+ "notificationType_mention": "当有人提到你时"
6
6
  }
@@ -1,3 +1,3 @@
1
- {
2
- "user-mentioned-you-in": "<strong>%1</strong> 在 <strong>%2</strong>提到你"
1
+ {
2
+ "user-mentioned-you-in": "<strong>%1</strong> 在 <strong>%2</strong>提到你"
3
3
  }
package/library.js CHANGED
@@ -5,6 +5,7 @@
5
5
  const _ = require('lodash');
6
6
  const validator = require('validator');
7
7
  const entitiesDecode = require('html-entities').decode;
8
+ const cheerio = require('cheerio');
8
9
 
9
10
  const nconf = require.main.require('nconf');
10
11
  const winston = require.main.require('winston');
@@ -36,6 +37,7 @@ const parts = {
36
37
  };
37
38
  const regex = RegExp(`${parts.before}${parts.main}`, 'gu');
38
39
  const isLatinMention = /@[\w\d\-_.@]+$/;
40
+ const hasAnchors = /<a.*>.*<\/a>/i;
39
41
 
40
42
  const Mentions = module.exports;
41
43
 
@@ -332,11 +334,12 @@ async function createNotification(postData, nidType, notificationText) {
332
334
  }
333
335
 
334
336
  Mentions.parsePost = async (data) => {
335
- if (!data || !data.postData || !data.postData.content) {
337
+ const { postData, type } = data;
338
+ if (!postData.content) {
336
339
  return data;
337
340
  }
338
341
 
339
- const parsed = await Mentions.parseRaw(data.postData.content);
342
+ const parsed = await Mentions.parseRaw(postData.content, type);
340
343
  data.postData.content = parsed;
341
344
  return data;
342
345
  };
@@ -345,7 +348,7 @@ function removePunctuationSuffix(string) {
345
348
  return string.replace(/[!?.]*$/, '');
346
349
  }
347
350
 
348
- function getMatches(content, isMarkdown = false) {
351
+ async function getMatches(content, isMarkdown = false) {
349
352
  const splitContent = utility.split(content, isMarkdown, false, true);
350
353
  let matches = [];
351
354
  splitContent.forEach((cleanedContent, i) => {
@@ -354,12 +357,42 @@ function getMatches(content, isMarkdown = false) {
354
357
  }
355
358
  });
356
359
 
357
- return { splitContent, matches };
360
+ const joined = splitContent.join('');
361
+ const parseAnchors = joined.match(hasAnchors);
362
+ const urlMap = new Map();
363
+ if (!isMarkdown && parseAnchors) {
364
+ const $ = cheerio.load(splitContent.join(''));
365
+ const anchors = $('a');
366
+ const urls = new Set();
367
+ Array.from(anchors).forEach((anchor) => {
368
+ const text = $(anchor).prop('innerText');
369
+ const match = text.match(regex);
370
+ if (match) {
371
+ urls.add($(anchor).attr('href'));
372
+ }
373
+ });
374
+
375
+ // Filter out urls that don't backreference to a remote id
376
+ const backrefs = 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
+ }
389
+
390
+ return { splitContent, matches, urlMap };
358
391
  }
359
392
 
360
393
  Mentions.getMatches = async (content) => {
361
394
  // Exported method only accepts markdown, also filters out dupes and matches to ensure slugs exist
362
- let { matches } = getMatches(content, true);
395
+ let { matches } = await getMatches(content, true);
363
396
  matches = await filterMatches(matches);
364
397
  const ids = await Promise.all(matches.map(async m => User.getUidByUserslug(m.slice(1).toLowerCase())));
365
398
  matches = matches.map((slug, idx) => (ids[idx] ? {
@@ -377,11 +410,15 @@ async function filterMatches(matches) {
377
410
  return matches.filter((m, i) => exists[[i]]);
378
411
  }
379
412
 
380
- Mentions.parseRaw = async (content) => {
413
+ Mentions.parseRaw = async (content, type = 'default') => {
414
+ if (type === 'plaintext') {
415
+ return content;
416
+ }
417
+
381
418
  // Note: Mentions.clean explicitly can't be called here because I need the content unstripped
382
- let { splitContent, matches } = getMatches(content);
419
+ let { splitContent, matches, urlMap } = await getMatches(content);
383
420
 
384
- if (!matches.length) {
421
+ if (!matches.length && !urlMap.size) {
385
422
  return content;
386
423
  }
387
424
 
@@ -395,6 +432,7 @@ Mentions.parseRaw = async (content) => {
395
432
  return atIndex !== 0 ? match.slice(atIndex) : match;
396
433
  });
397
434
 
435
+ // Convert matches to anchor html
398
436
  await Promise.all(matches.map(async (match) => {
399
437
  const slug = slugify(match.slice(1));
400
438
  match = removePunctuationSuffix(match);
@@ -402,7 +440,7 @@ Mentions.parseRaw = async (content) => {
402
440
  const cid = await categories.getCidByHandle(slug);
403
441
  const { groupExists, user, category } = await utils.promiseParallel({
404
442
  groupExists: Groups.existsBySlug(slug),
405
- user: User.getUserFields(uid, ['uid', 'username', 'fullname', 'url']),
443
+ user: User.getUserFields(uid, ['uid', 'username', 'userslug', 'fullname', 'url']),
406
444
  category: categories.getCategoryFields(cid, ['slug']),
407
445
  });
408
446
 
@@ -411,17 +449,20 @@ Mentions.parseRaw = async (content) => {
411
449
 
412
450
  switch (true) {
413
451
  case !!uid: {
414
- url = utils.isNumber(user.uid) ? `${nconf.get('url')}/user/${slug}` : (user.url || user.uid);
452
+ url = `/user/${encodeURIComponent(user.userslug)}`;
453
+ if (type.startsWith('activitypub') && !utils.isNumber(uid)) {
454
+ url = user.url || user.uid;
455
+ }
415
456
  break;
416
457
  }
417
458
 
418
459
  case !!cid: {
419
- url = `${nconf.get('url')}/category/${category.slug}`;
460
+ url = `/category/${category.slug}`;
420
461
  break;
421
462
  }
422
463
 
423
464
  case !!groupExists: {
424
- url = `${nconf.get('url')}/groups/${slug}`;
465
+ url = `/groups/${slug}`;
425
466
  break;
426
467
  }
427
468
  }
@@ -461,7 +502,20 @@ Mentions.parseRaw = async (content) => {
461
502
  }
462
503
  }));
463
504
 
464
- return splitContent.join('');
505
+ const parsed = splitContent.join('');
506
+
507
+ // Modify existing anchors to local profile
508
+ const $ = cheerio.load(parsed);
509
+ const anchors = $('a');
510
+ Array.from(anchors).forEach((anchor) => {
511
+ const $anchor = $(anchor);
512
+ const url = $anchor.attr('href');
513
+ if (urlMap.has(url)) {
514
+ $anchor.attr('href', urlMap.get(url));
515
+ }
516
+ });
517
+
518
+ return $.html();
465
519
  };
466
520
 
467
521
  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.5.3",
3
+ "version": "4.6.1",
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,13 +22,15 @@
22
22
  "compatibility": "^4.0.0"
23
23
  },
24
24
  "dependencies": {
25
+ "cheerio": "^1.0.0-rc.12",
25
26
  "html-entities": "^2.3.2",
26
27
  "lodash": "4.17.21",
28
+ "sanitize-html": "^2.13.0",
27
29
  "validator": "^13.0.0"
28
30
  },
29
31
  "devDependencies": {
30
32
  "mocha": "10.4.0",
31
- "eslint": "9.2.0",
33
+ "eslint": "9.3.0",
32
34
  "eslint-config-nodebb": "0.2.1",
33
35
  "eslint-plugin-import": "2.29.1"
34
36
  }
package/plugin.json CHANGED
@@ -1,32 +1,32 @@
1
- {
2
- "id": "nodebb-plugin-mentions",
3
- "name": "Username Mentions",
4
- "description": "NodeBB Plugin that allows users to mention other users by prepending an '@' sign to their username",
5
- "url": "https://github.com/julianlam/nodebb-plugin-mentions",
6
- "library": "./library.js",
7
- "upgrades": [
8
- "upgrades/mentions_delete_mentions_set_zset.js"
9
- ],
10
- "hooks": [
11
- { "hook": "static:app.load", "method": "init" },
12
- { "hook": "filter:admin.header.build", "method": "addAdminNavigation" },
13
- { "hook": "filter:parse.post", "method": "parsePost" },
14
- { "hook": "filter:parse.raw", "method": "parseRaw" },
15
- { "hook": "action:post.save", "method": "notify" },
16
- { "hook": "action:post.edit", "method": "notify" },
17
- { "hook": "action:posts.purge", "method": "actionPostsPurge" },
18
- { "hook": "action:messaging.save", "method": "notifyMessage" },
19
- { "hook": "filter:notifications.addFilters", "method": "addFilters" },
20
- { "hook": "filter:user.notificationTypes", "method": "notificationTypes" },
21
- { "hook": "filter:users.addFields", "method": "addFields" }
22
- ],
23
- "scripts": [
24
- "static/autofill.js"
25
- ],
26
- "modules": {
27
- "../admin/plugins/mentions.js": "./static/admin.js"
28
- },
29
- "languages": "languages",
30
- "defaultLang": "en_GB",
31
- "templates": "templates"
1
+ {
2
+ "id": "nodebb-plugin-mentions",
3
+ "name": "Username Mentions",
4
+ "description": "NodeBB Plugin that allows users to mention other users by prepending an '@' sign to their username",
5
+ "url": "https://github.com/julianlam/nodebb-plugin-mentions",
6
+ "library": "./library.js",
7
+ "upgrades": [
8
+ "upgrades/mentions_delete_mentions_set_zset.js"
9
+ ],
10
+ "hooks": [
11
+ { "hook": "static:app.load", "method": "init" },
12
+ { "hook": "filter:admin.header.build", "method": "addAdminNavigation" },
13
+ { "hook": "filter:parse.post", "method": "parsePost" },
14
+ { "hook": "filter:parse.raw", "method": "parseRaw" },
15
+ { "hook": "action:post.save", "method": "notify" },
16
+ { "hook": "action:post.edit", "method": "notify" },
17
+ { "hook": "action:posts.purge", "method": "actionPostsPurge" },
18
+ { "hook": "action:messaging.save", "method": "notifyMessage" },
19
+ { "hook": "filter:notifications.addFilters", "method": "addFilters" },
20
+ { "hook": "filter:user.notificationTypes", "method": "notificationTypes" },
21
+ { "hook": "filter:users.addFields", "method": "addFields" }
22
+ ],
23
+ "scripts": [
24
+ "static/autofill.js"
25
+ ],
26
+ "modules": {
27
+ "../admin/plugins/mentions.js": "./static/admin.js"
28
+ },
29
+ "languages": "languages",
30
+ "defaultLang": "en_GB",
31
+ "templates": "templates"
32
32
  }
package/static/.eslintrc CHANGED
@@ -1,3 +1,3 @@
1
- {
2
- "extends": "nodebb/public"
3
- }
1
+ {
2
+ "extends": "nodebb/public"
3
+ }