@vacantthinker/firefox-addon-framework-easy 2026.526.908 → 2026.526.1059

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/README.md CHANGED
@@ -114,6 +114,10 @@ export async function serviceElementPicker(message) { }
114
114
 
115
115
  export async function serviceGetFullPageRectData(message) { }
116
116
 
117
+ export async function serviceFindAllMagnetLink(message) { }
118
+
119
+ export async function serviceDealWithMagnetLink(message) { }
120
+
117
121
  ```
118
122
 
119
123
  ### 📄 File: `src/serviceFetch.js`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vacantthinker/firefox-addon-framework-easy",
3
- "version": "2026.0526.0908",
3
+ "version": "2026.0526.1059",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "publishConfig": {
@@ -1,3 +1,11 @@
1
+ import {serviceGetCurrentDateYYYYMMDDHHMMSS} from './serviceGet.js';
2
+ import {
3
+ serviceCopyContentToClipboard,
4
+ serviceRemoveIllegalWord,
5
+ serviceSaveContentToLocal,
6
+ } from './serviceOpContent.js';
7
+ import {browserNotificationCreate} from './browserNotification.js';
8
+
1
9
  /**
2
10
  * will get => {{x, y, width, height, uniqueSelector}}
3
11
  * @param message{{
@@ -144,7 +152,8 @@ export async function serviceElementPicker(message) {
144
152
  }
145
153
 
146
154
  /**
147
- * will get => {{x, y, width, height,}}
155
+ * middle ware, output: Object.assign({}, message, {x, y, width, height,})
156
+ *
148
157
  * @param message{{
149
158
  * tabId:number,
150
159
  * act:string
@@ -174,3 +183,114 @@ export async function serviceGetFullPageRectData(message) {
174
183
  },
175
184
  });
176
185
  }
186
+
187
+ /**
188
+ * middle ware, output: Object.assign({}, message, {data})
189
+ *
190
+ * serviceFindAllMagnetLink({
191
+ * tabId, title, act, ...
192
+ * })
193
+ *
194
+ * @param message{{
195
+ * tabId:number,
196
+ * title:string,
197
+ * act: string,
198
+ * }}
199
+ */
200
+ export async function serviceFindAllMagnetLink(message) {
201
+ let {tabId} = message;
202
+ const assign = Object.assign({}, message);
203
+
204
+ await browser.scripting.executeScript({
205
+ target: {tabId},
206
+ args: [assign],
207
+ func: async (message) => {
208
+ if (message) {
209
+ function findAllMagnetLinks() {
210
+ const magnets = new Set(); // Prevents duplicates
211
+
212
+ // --- Type 1: Find inside ANY element's attributes ---
213
+ const attributeSelector = '*[href*="magnet:"], *[data-url*="magnet:"], *[data-magnet*="magnet:"], *[data-href*="magnet:"]';
214
+ const attrElements = document.querySelectorAll(attributeSelector);
215
+
216
+ attrElements.forEach(el => {
217
+ // Check every attribute of the element to find the one holding the magnet string
218
+ for (let attr of el.attributes) {
219
+ if (attr.value.includes('magnet:?xt=')) {
220
+ magnets.add(attr.value.trim());
221
+ }
222
+ }
223
+ });
224
+
225
+ // --- Type 2: Find inside raw text (for <div>, <span>, <td>, etc.) ---
226
+ // We target elements that don't have children to avoid grabbing huge parent container blocks
227
+ const allElements = document.querySelectorAll(
228
+ 'div, span, td, p, a, button');
229
+ allElements.forEach(el => {
230
+ if (el.children.length === 0) { // Deepest element
231
+ const text = el.textContent.trim();
232
+ if (text.includes('magnet:?xt=')) {
233
+ // Extract just the magnet link using Regex in case there is surrounding text
234
+ const match = text.match(/magnet:\?xt=[^\s"'<>]+/);
235
+ if (match) {
236
+ magnets.add(match[0]);
237
+ }
238
+ }
239
+ }
240
+ });
241
+
242
+ return Array.from(magnets);
243
+ }
244
+
245
+ await browser.runtime.sendMessage(Object.assign(
246
+ {},
247
+ message,
248
+ {
249
+ data: findAllMagnetLinks(),
250
+ },
251
+ ));
252
+
253
+ // todo end if(message)
254
+ }
255
+ },
256
+ });
257
+ }
258
+
259
+ /**
260
+ *
261
+ * @param message{{
262
+ * title:string,
263
+ * data: [string],
264
+ * handleOption: 'clipboard'|'txt'|'clipboardAndTxt'
265
+ * }}
266
+ * @returns {Promise<void>}
267
+ */
268
+ export async function serviceDealWithMagnetLink(message) {
269
+
270
+ let {title, data, handleOption} = message;
271
+ let titleCleaned = serviceRemoveIllegalWord(title);
272
+ console.info('content.length', data.length);
273
+
274
+ if (Array.isArray(data) && data.length >= 1) {
275
+ let content = `${data.join('\n')}\n`;
276
+ let filename = [
277
+ 'magnet-link',
278
+ titleCleaned,
279
+ serviceGetCurrentDateYYYYMMDDHHMMSS()].join(' ');
280
+
281
+ if (handleOption === 'clipboard') {
282
+ serviceCopyContentToClipboard(content);
283
+ }
284
+ else if (handleOption === 'txt') {
285
+ serviceSaveContentToLocal(content, filename);
286
+ }
287
+ else if (handleOption === 'clipboardAndTxt') {
288
+ serviceCopyContentToClipboard(content);
289
+ serviceSaveContentToLocal(content, filename);
290
+ }
291
+ }
292
+ else {
293
+ // todo notification => magnet link not found!
294
+ await browserNotificationCreate('magnet link not found!');
295
+ }
296
+ }