nodebb-plugin-facebook-post 1.0.29 → 1.0.31

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
@@ -73,16 +73,33 @@ function absolutizeUrl(url) {
73
73
  return `${base}/${url}`;
74
74
  }
75
75
 
76
+ function getApexDomain(hostname) {
77
+ const parts = hostname.split('.');
78
+ return parts.length <= 2 ? hostname : parts.slice(-2).join('.');
79
+ }
80
+
76
81
  function isForumHosted(urlAbs) {
77
82
  const base = getForumBaseUrl();
78
83
  if (!base) return false;
79
84
  try {
80
- return new URL(urlAbs).host === new URL(base).host;
85
+ const imgHost = new URL(urlAbs).host;
86
+ const forumHost = new URL(base).host;
87
+ return imgHost === forumHost || getApexDomain(imgHost) === getApexDomain(forumHost);
81
88
  } catch {
82
89
  return false;
83
90
  }
84
91
  }
85
92
 
93
+ function decodeHtmlEntities(str) {
94
+ return str
95
+ .replace(/&amp;/g, '&')
96
+ .replace(/&lt;/g, '<')
97
+ .replace(/&gt;/g, '>')
98
+ .replace(/&quot;/g, '"')
99
+ .replace(/&#x([0-9a-fA-F]+);/gi, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
100
+ .replace(/&#(\d+);/g, (_, dec) => String.fromCharCode(Number(dec)));
101
+ }
102
+
86
103
  function extractImageUrlsFromContent(rawContent) {
87
104
  const urls = new Set();
88
105
  if (!rawContent) return [];
@@ -212,7 +229,7 @@ async function publishFeedPost({ message, link, photoIds }) {
212
229
 
213
230
  async function postToFacebook(ctx) {
214
231
  const rawContent = ctx.post.content || '';
215
- const topicTitle = ctx.topic.title || 'Nouveau sujet';
232
+ const topicTitle = decodeHtmlEntities(ctx.topic.title || 'Nouveau sujet');
216
233
  const author = ctx.user.username || 'Quelqu\u2019un';
217
234
  const link = ctx.topicUrlAbs;
218
235
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-facebook-post",
3
- "version": "1.0.29",
3
+ "version": "1.0.31",
4
4
  "description": "Auto-post new NodeBB topics to a fixed Facebook Page (text + NodeBB uploads + place id).",
5
5
  "main": "library.js",
6
6
  "dependencies": {
@@ -16,34 +16,42 @@
16
16
  }
17
17
 
18
18
  function injectUI($composer) {
19
- if ($composer.find('[data-fbpost-wrap]').length) return;
19
+ if ($composer.find('[data-fbpost-btn]').length) return;
20
20
 
21
- const html = `
22
- <div class="mb-2" data-fbpost-wrap>
23
- <div class="form-check mb-2">
24
- <input type="checkbox" class="form-check-input" id="fbPostEnabled" data-fbpost-enabled>
25
- <label class="form-check-label" for="fbPostEnabled">Publier ce nouveau topic sur Facebook (et Insta si activé)</label>
26
- </div>
27
- </div>
28
- `;
21
+ const $btn = $(`
22
+ <button type="button" class="btn btn-sm btn-link" data-fbpost-btn
23
+ title="Publier ce topic sur Facebook (cliquer pour activer)"
24
+ style="opacity:0.4; color:#1877F2; font-size:1.2em; padding:2px 6px;">
25
+ <i class="fab fa-facebook-f"></i>
26
+ </button>
27
+ `);
29
28
 
30
- const $write = $composer.find('.write').first();
31
- if ($write.is('textarea')) {
32
- // .write est la textarea elle-même — injecter après son conteneur parent
33
- $write.parent().after(html);
34
- } else if ($write.length) {
35
- $write.prepend(html);
29
+ $btn.on('click', function () {
30
+ const active = $(this).data('fbpost-active');
31
+ $(this).data('fbpost-active', !active)
32
+ .attr('title', !active
33
+ ? 'Publier sur Facebook (actif — cliquer pour désactiver)'
34
+ : 'Publier ce topic sur Facebook (cliquer pour activer)')
35
+ .css('opacity', !active ? '1' : '0.4');
36
+ });
37
+
38
+ // Injecter dans la barre d'outils du composeur
39
+ const $toolbar = $composer.find('.toolbar, .formatting-bar, [data-toolbar]').first();
40
+ if ($toolbar.length) {
41
+ // Si la toolbar contient des <li>, on enveloppe
42
+ if ($toolbar.find('li').length) {
43
+ $toolbar.append($('<li>').append($btn));
44
+ } else {
45
+ $toolbar.append($btn);
46
+ }
36
47
  } else {
37
- const $target = $composer.find('.composer-body, .composer-content').first();
38
- if ($target.length) $target.prepend(html);
39
- else $composer.prepend(html);
48
+ // Fallback : avant la zone de texte
49
+ $composer.find('.write').first().before($btn);
40
50
  }
41
51
 
42
- // NodeBB 4.x fires 'action:composer.submit' with { composerData } (the object
43
- // sent to the socket). Modifying composerData by reference is enough.
44
52
  $(window).off('action:composer.submit.fbpost')
45
53
  .on('action:composer.submit.fbpost', function (ev2, data) {
46
- const enabled = $enabled.is(':checked');
54
+ const enabled = !!$composer.find('[data-fbpost-btn]').data('fbpost-active');
47
55
  const postData = (data && data.composerData) || (data && data.postData) || data;
48
56
  if (!postData || typeof postData !== 'object') return;
49
57
  postData.fbPostEnabled = enabled;
@@ -64,4 +72,3 @@
64
72
  }
65
73
  });
66
74
  })();
67
-