@vacantthinker/firefox-addon-framework-easy 2026.611.821 → 2026.611.1153

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 (70) hide show
  1. package/README.md +0 -217
  2. package/dist/BaseORM.d.ts +41 -0
  3. package/dist/BaseORM.d.ts.map +1 -0
  4. package/dist/BaseORM.js +77 -0
  5. package/dist/browserDownload.d.ts +9 -0
  6. package/dist/browserDownload.d.ts.map +1 -0
  7. package/dist/browserDownload.js +10 -0
  8. package/dist/browserNotification.d.ts +8 -0
  9. package/dist/browserNotification.d.ts.map +1 -0
  10. package/dist/browserNotification.js +17 -0
  11. package/dist/browserRuntime.d.ts +41 -0
  12. package/dist/browserRuntime.d.ts.map +1 -0
  13. package/dist/browserRuntime.js +61 -0
  14. package/dist/browserTab.d.ts +34 -0
  15. package/dist/browserTab.d.ts.map +1 -0
  16. package/dist/browserTab.js +105 -0
  17. package/dist/generate.d.ts +13 -0
  18. package/dist/generate.d.ts.map +1 -0
  19. package/dist/generate.js +99 -0
  20. package/dist/index.d.ts +16 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +15 -0
  23. package/dist/opStorage.d.ts +40 -0
  24. package/dist/opStorage.d.ts.map +1 -0
  25. package/dist/opStorage.js +57 -0
  26. package/dist/opTab.d.ts +82 -0
  27. package/dist/opTab.d.ts.map +1 -0
  28. package/dist/opTab.js +152 -0
  29. package/dist/serviceCommon.d.ts +8 -0
  30. package/dist/serviceCommon.d.ts.map +1 -0
  31. package/dist/serviceCommon.js +21 -0
  32. package/dist/serviceFetch.d.ts +23 -0
  33. package/dist/serviceFetch.d.ts.map +1 -0
  34. package/dist/serviceFetch.js +38 -0
  35. package/dist/serviceGet.d.ts +13 -0
  36. package/dist/serviceGet.d.ts.map +1 -0
  37. package/dist/serviceGet.js +24 -0
  38. package/dist/serviceOpContent.d.ts +24 -0
  39. package/dist/serviceOpContent.d.ts.map +1 -0
  40. package/dist/serviceOpContent.js +69 -0
  41. package/dist/serviceOpJavascript.d.ts +41 -0
  42. package/dist/serviceOpJavascript.d.ts.map +1 -0
  43. package/dist/serviceOpJavascript.js +182 -0
  44. package/dist/servicePure.d.ts +18 -0
  45. package/dist/servicePure.d.ts.map +1 -0
  46. package/dist/servicePure.js +51 -0
  47. package/dist/serviceUpdateTabStyle.d.ts +17 -0
  48. package/dist/serviceUpdateTabStyle.d.ts.map +1 -0
  49. package/dist/serviceUpdateTabStyle.js +63 -0
  50. package/package.json +11 -4
  51. package/.github/workflows/npm-publish.yml +0 -34
  52. package/index.js +0 -17
  53. package/publish.sh +0 -81
  54. package/src/BaseORM.js +0 -66
  55. package/src/DomainORM.js +0 -11
  56. package/src/browserDownload.js +0 -23
  57. package/src/browserNotification.js +0 -22
  58. package/src/browserRuntime.js +0 -65
  59. package/src/browserRuntimeOnMessageCommon.js +0 -50
  60. package/src/browserTab.js +0 -138
  61. package/src/generate.js +0 -177
  62. package/src/opStorage.js +0 -76
  63. package/src/opTab.js +0 -237
  64. package/src/serviceCommon.js +0 -22
  65. package/src/serviceFetch.js +0 -65
  66. package/src/serviceGet.js +0 -31
  67. package/src/serviceOpContent.js +0 -83
  68. package/src/serviceOpJavascript.js +0 -346
  69. package/src/servicePure.js +0 -42
  70. package/src/serviceUpdateTabStyle.js +0 -130
@@ -0,0 +1,69 @@
1
+ import { browserRuntimePlatformInfo } from './browserRuntime';
2
+ import { generateMkvScriptForSystemFedora, generateMkvScriptForSystemWindows, } from './generate';
3
+ /**
4
+ * Maps file extensions to MIME types.
5
+ */
6
+ const EXT_MIME_MAP = {
7
+ txt: 'text/plain',
8
+ json: 'application/json',
9
+ js: 'application/javascript',
10
+ sh: 'application/x-sh',
11
+ };
12
+ /**
13
+ * Copies text content to the system clipboard.
14
+ */
15
+ export async function serviceCopyContentToClipboard(data) {
16
+ return await window.navigator.clipboard.writeText(data);
17
+ }
18
+ /**
19
+ * Saves content to a local file.
20
+ * @param content The content string.
21
+ * @param filename The base filename.
22
+ * @param ext The file extension.
23
+ */
24
+ export function serviceSaveContentToLocal(content, filename, ext = 'txt') {
25
+ const mimeType = EXT_MIME_MAP[ext] || 'text/plain';
26
+ const blob = new Blob([content], { type: mimeType });
27
+ const url = URL.createObjectURL(blob);
28
+ const eleA = document.createElement('a');
29
+ eleA.href = url;
30
+ eleA.download = `${filename}.${ext}`;
31
+ // Programmatically trigger download
32
+ eleA.click();
33
+ // Cleanup
34
+ URL.revokeObjectURL(url);
35
+ }
36
+ /**
37
+ * Generates an MKVToolNix script based on the current OS.
38
+ * @param videoInfo - The object containing vid and videoTitle.
39
+ */
40
+ export async function serviceGenerateMkvToolNixScript(videoInfo) {
41
+ const platformInfo = await browserRuntimePlatformInfo();
42
+ if (platformInfo.os === 'win') {
43
+ const content = generateMkvScriptForSystemWindows(videoInfo);
44
+ serviceSaveContentToLocal(content, videoInfo.videoTitle, 'js');
45
+ }
46
+ else if (platformInfo.os === 'linux') {
47
+ const content = generateMkvScriptForSystemFedora(videoInfo);
48
+ serviceSaveContentToLocal(content, videoInfo.videoTitle, 'sh');
49
+ }
50
+ }
51
+ /**
52
+ * Cleans a string to make it a valid filename.
53
+ * @param value The raw string.
54
+ * @returns A cleaned filename string.
55
+ */
56
+ export function serviceRemoveIllegalWord(value) {
57
+ if (!value)
58
+ return '';
59
+ // Get the first line and trim whitespace
60
+ let name = value.trim().split(/\r?\n/)[0];
61
+ // Replace punctuation, symbols, and control chars with space
62
+ name = name.replace(/[\p{P}\p{S}\p{C}]/gu, ' ');
63
+ // Replace specific legacy forbidden characters
64
+ name = name.replace(/[~"#%&*:<>?/\\{|}]/g, ' ');
65
+ // Normalize whitespaces
66
+ name = name.replace(/[\s\u3000]+/g, ' ').trim();
67
+ // Remove leading/trailing dots or hyphens
68
+ return name.replace(/^[-.]+|[-.]+$/g, '');
69
+ }
@@ -0,0 +1,41 @@
1
+ interface ScreenRect {
2
+ x: number;
3
+ y: number;
4
+ width: number;
5
+ height: number;
6
+ }
7
+ interface ActionMessage {
8
+ tabId: number;
9
+ act: string;
10
+ }
11
+ interface MagnetLinkMessage extends ActionMessage {
12
+ title: string;
13
+ data?: string[];
14
+ handleOption?: 'clipboard' | 'txt' | 'clipboardAndTxt';
15
+ }
16
+ /**
17
+ * Captures a tab's screenshot and triggers a local download in the target tab.
18
+ */
19
+ export declare function serviceTakeScreenshot({ tabId, filename, rect }: {
20
+ tabId: number;
21
+ filename: string;
22
+ rect: ScreenRect;
23
+ }): Promise<void>;
24
+ /**
25
+ * Enables an element picker overlay in the target tab.
26
+ */
27
+ export declare function serviceElementPicker(message: ActionMessage): Promise<void>;
28
+ /**
29
+ * Gets the bounding rectangle of the full page.
30
+ */
31
+ export declare function serviceGetFullPageRectData(message: ActionMessage): Promise<void>;
32
+ /**
33
+ * Scans the page for magnet links.
34
+ */
35
+ export declare function serviceFindAllMagnetLink(message: MagnetLinkMessage): Promise<void>;
36
+ /**
37
+ * Handles the processing of collected magnet links (clipboard or file).
38
+ */
39
+ export declare function serviceDealWithMagnetLink(message: MagnetLinkMessage): Promise<void>;
40
+ export {};
41
+ //# sourceMappingURL=serviceOpJavascript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serviceOpJavascript.d.ts","sourceRoot":"","sources":["../src/serviceOpJavascript.ts"],"names":[],"mappings":"AAUA,UAAU,UAAU;IAClB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,UAAU,aAAa;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED,UAAU,iBAAkB,SAAQ,aAAa;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,CAAC,EAAE,WAAW,GAAG,KAAK,GAAG,iBAAiB,CAAC;CACxD;AAID;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,EAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAC,EAAE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,UAAU,CAAA;CACjB,GAAG,OAAO,CAAC,IAAI,CAAC,CAchB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAsFhF;AAED;;GAEG;AACH,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAatF;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BxF;AAED;;GAEG;AACH,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBzF"}
@@ -0,0 +1,182 @@
1
+ import { serviceGetCurrentDateYYYYMMDDHHMMSS } from './serviceGet';
2
+ import { serviceCopyContentToClipboard, serviceRemoveIllegalWord, serviceSaveContentToLocal, } from './serviceOpContent';
3
+ import { browserNotificationCreate } from './browserNotification';
4
+ // --- Services ---
5
+ /**
6
+ * Captures a tab's screenshot and triggers a local download in the target tab.
7
+ */
8
+ export async function serviceTakeScreenshot({ tabId, filename, rect }) {
9
+ const dataURI = await browser.tabs.captureTab(tabId, { rect });
10
+ await browser.scripting.executeScript({
11
+ target: { tabId },
12
+ args: [{ dataURI, filename }],
13
+ func: (message) => {
14
+ const { dataURI, filename } = message;
15
+ const a = document.createElement('a');
16
+ a.href = dataURI;
17
+ a.download = filename;
18
+ a.click();
19
+ },
20
+ });
21
+ }
22
+ /**
23
+ * Enables an element picker overlay in the target tab.
24
+ */
25
+ export async function serviceElementPicker(message) {
26
+ await browser.scripting.executeScript({
27
+ target: { tabId: message.tabId },
28
+ args: [message],
29
+ func: (async (message) => {
30
+ const overlayId = 'extension-element-highlighter-overlay';
31
+ let overlay = document.getElementById(overlayId);
32
+ if (!overlay) {
33
+ overlay = document.createElement('div');
34
+ overlay.id = overlayId;
35
+ overlay.style.cssText = `
36
+ position: fixed !important; top: 0 !important; left: 0 !important;
37
+ width: 0 !important; height: 0 !important;
38
+ background-color: rgba(255, 0, 85, 0.2) !important;
39
+ outline: 2px dashed #ff0055 !important; outline-offset: -2px !important;
40
+ z-index: 2147483647 !important; pointer-events: none !important;
41
+ transition: all 0.05s ease-out !important; display: none !important;
42
+ `;
43
+ document.documentElement.appendChild(overlay);
44
+ }
45
+ function getUniqueSelector(el) {
46
+ const path = [];
47
+ let current = el;
48
+ while (current && current.nodeType === Node.ELEMENT_NODE) {
49
+ let selector = current.nodeName.toLowerCase();
50
+ if (current.id) {
51
+ selector += `#${current.id}`;
52
+ path.unshift(selector);
53
+ break;
54
+ }
55
+ else {
56
+ let sib = current, nth = 1;
57
+ while ((sib = sib.previousElementSibling) && sib.nodeName.toLowerCase() === selector)
58
+ nth++;
59
+ if (nth !== 1)
60
+ selector += `:nth-of-type(${nth})`;
61
+ }
62
+ path.unshift(selector);
63
+ current = current.parentElement;
64
+ }
65
+ return path.join(' > ');
66
+ }
67
+ function handleMouseOver(e) {
68
+ const target = e.target;
69
+ if (target.id === overlayId || !overlay)
70
+ return;
71
+ const rect = target.getBoundingClientRect();
72
+ Object.assign(overlay.style, {
73
+ display: 'block',
74
+ top: `${rect.top}px`, left: `${rect.left}px`,
75
+ width: `${rect.width}px`, height: `${rect.height}px`,
76
+ });
77
+ document.body.style.setProperty('cursor', 'crosshair', 'important');
78
+ }
79
+ async function handleElementClick(e) {
80
+ e.preventDefault();
81
+ e.stopPropagation();
82
+ const target = e.target;
83
+ stopPickingMode();
84
+ const clientRect = target.getBoundingClientRect();
85
+ const rect = {
86
+ height: clientRect.height,
87
+ width: clientRect.width,
88
+ x: clientRect.left + window.scrollX,
89
+ y: clientRect.top + window.scrollY,
90
+ };
91
+ await browser.runtime.sendMessage({
92
+ ...message,
93
+ rect,
94
+ uniqueSelector: getUniqueSelector(target),
95
+ });
96
+ }
97
+ function stopPickingMode() {
98
+ document.removeEventListener('mouseover', handleMouseOver, true);
99
+ document.removeEventListener('click', handleElementClick, true);
100
+ document.body.style.removeProperty('cursor');
101
+ overlay?.remove();
102
+ }
103
+ document.addEventListener('mouseover', handleMouseOver, true);
104
+ document.addEventListener('click', handleElementClick, true);
105
+ }),
106
+ });
107
+ }
108
+ /**
109
+ * Gets the bounding rectangle of the full page.
110
+ */
111
+ export async function serviceGetFullPageRectData(message) {
112
+ await browser.scripting.executeScript({
113
+ target: { tabId: message.tabId },
114
+ args: [message],
115
+ func: (message) => {
116
+ const rect = {
117
+ x: 0, y: 0,
118
+ width: document.documentElement.scrollWidth,
119
+ height: document.documentElement.scrollHeight,
120
+ };
121
+ browser.runtime.sendMessage({ ...message, rect });
122
+ },
123
+ });
124
+ }
125
+ /**
126
+ * Scans the page for magnet links.
127
+ */
128
+ export async function serviceFindAllMagnetLink(message) {
129
+ await browser.scripting.executeScript({
130
+ target: { tabId: message.tabId },
131
+ args: [message],
132
+ func: (async (message) => {
133
+ const magnets = new Set();
134
+ // Type 1: Attribute selectors
135
+ const attrElements = document.querySelectorAll('*[href*="magnet:"], *[data-url*="magnet:"], *[data-magnet*="magnet:"], *[data-href*="magnet:"]');
136
+ attrElements.forEach(el => {
137
+ Array.from(el.attributes).forEach(attr => {
138
+ if (attr.value.includes('magnet:?xt='))
139
+ magnets.add(attr.value.trim());
140
+ });
141
+ });
142
+ // Type 2: Text content
143
+ document.querySelectorAll('div, span, td, p, a, button').forEach(el => {
144
+ if (el.children.length === 0) {
145
+ const text = el.textContent?.trim() || '';
146
+ const match = text.match(/magnet:\?xt=[^\s"'<>]+/);
147
+ if (match)
148
+ magnets.add(match[0]);
149
+ }
150
+ });
151
+ await browser.runtime.sendMessage({
152
+ ...message,
153
+ data: Array.from(magnets),
154
+ });
155
+ }),
156
+ });
157
+ }
158
+ /**
159
+ * Handles the processing of collected magnet links (clipboard or file).
160
+ */
161
+ export async function serviceDealWithMagnetLink(message) {
162
+ const { title, data, handleOption } = message;
163
+ const titleCleaned = serviceRemoveIllegalWord(title);
164
+ if (!Array.isArray(data) || data.length === 0) {
165
+ await browserNotificationCreate('magnet link not found!');
166
+ return;
167
+ }
168
+ const content = `${data.join('\n')}\n`;
169
+ const filename = ['magnet-link', titleCleaned, serviceGetCurrentDateYYYYMMDDHHMMSS()].join(' ');
170
+ switch (handleOption) {
171
+ case 'clipboard':
172
+ await serviceCopyContentToClipboard(content);
173
+ break;
174
+ case 'txt':
175
+ serviceSaveContentToLocal(content, filename);
176
+ break;
177
+ case 'clipboardAndTxt':
178
+ await serviceCopyContentToClipboard(content);
179
+ serviceSaveContentToLocal(content, filename);
180
+ break;
181
+ }
182
+ }
@@ -0,0 +1,18 @@
1
+ export interface YoutubeVideoInfo {
2
+ videolink: string;
3
+ vid: string;
4
+ }
5
+ export interface YoutubePlaylistInfo {
6
+ playlistVideolink: string;
7
+ playlistId: string;
8
+ }
9
+ /**
10
+ * Extracts video ID and creates a clean YouTube URL.
11
+ * Supports: youtube.com/watch?v=, youtu.be/, and youtube.com/shorts/
12
+ */
13
+ export declare function servicePureVideolinkYTB(videolinkOrigin: string): YoutubeVideoInfo | null;
14
+ /**
15
+ * Extracts playlist ID and creates a clean YouTube playlist URL.
16
+ */
17
+ export declare function servicePurePlaylistVideolinkYTB(videolinkOrigin: string): YoutubePlaylistInfo | null;
18
+ //# sourceMappingURL=servicePure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"servicePure.d.ts","sourceRoot":"","sources":["../src/servicePure.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,mBAAmB;IAClC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,eAAe,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CA6BxF;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAAC,eAAe,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAgBnG"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Extracts video ID and creates a clean YouTube URL.
3
+ * Supports: youtube.com/watch?v=, youtu.be/, and youtube.com/shorts/
4
+ */
5
+ export function servicePureVideolinkYTB(videolinkOrigin) {
6
+ if (!videolinkOrigin)
7
+ return null;
8
+ try {
9
+ const url = new URL(videolinkOrigin);
10
+ let vid = null;
11
+ // 1. Standard watch URL: youtube.com/watch?v=ID
12
+ vid = url.searchParams.get('v');
13
+ // 2. Short URL: youtu.be/ID
14
+ if (!vid && url.hostname.includes('youtu.be')) {
15
+ vid = url.pathname.slice(1);
16
+ }
17
+ // 3. Shorts URL: youtube.com/shorts/ID
18
+ if (!vid && url.pathname.startsWith('/shorts/')) {
19
+ vid = url.pathname.split('/')[2];
20
+ }
21
+ if (!vid)
22
+ return null;
23
+ return {
24
+ videolink: `https://www.youtube.com/watch?v=${vid}`,
25
+ vid,
26
+ };
27
+ }
28
+ catch {
29
+ return null; // Invalid URL
30
+ }
31
+ }
32
+ /**
33
+ * Extracts playlist ID and creates a clean YouTube playlist URL.
34
+ */
35
+ export function servicePurePlaylistVideolinkYTB(videolinkOrigin) {
36
+ if (!videolinkOrigin)
37
+ return null;
38
+ try {
39
+ const url = new URL(videolinkOrigin);
40
+ const playlistId = url.searchParams.get('list');
41
+ if (!playlistId)
42
+ return null;
43
+ return {
44
+ playlistVideolink: `https://www.youtube.com/playlist?list=${playlistId}`,
45
+ playlistId,
46
+ };
47
+ }
48
+ catch {
49
+ return null; // Invalid URL
50
+ }
51
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Style management service for browser tabs.
3
+ */
4
+ /**
5
+ * Update the text color for all elements globally.
6
+ */
7
+ export declare function serviceUpdataALLTextNodeColor(tabId: number, color: string): Promise<void>;
8
+ /**
9
+ * Update the background color for all elements globally.
10
+ */
11
+ export declare function serviceUpdataALLNodeBackgroundColor(tabId: number, bgColor: string): Promise<void>;
12
+ /**
13
+ * Adjust font size globally by a delta value.
14
+ * Uses recursive DOM traversal to support Shadow DOM elements.
15
+ */
16
+ export declare function serviceIncreaseAllTextFontSize(tabId: number, delta: number): Promise<void>;
17
+ //# sourceMappingURL=serviceUpdateTabStyle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serviceUpdateTabStyle.d.ts","sourceRoot":"","sources":["../src/serviceUpdateTabStyle.ts"],"names":[],"mappings":"AAAA;;GAEG;AAaH;;GAEG;AACH,wBAAsB,6BAA6B,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/F;AAED;;GAEG;AACH,wBAAsB,mCAAmC,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIvG;AASD;;;GAGG;AACH,wBAAsB,8BAA8B,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkChG"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Style management service for browser tabs.
3
+ */
4
+ /**
5
+ * Apply a CSS string globally to the target tab.
6
+ * This is the most efficient way to override styles without traversing the DOM.
7
+ */
8
+ async function applyGlobalCss(tabId, css) {
9
+ await browser.scripting.insertCSS({
10
+ target: { tabId },
11
+ css: css,
12
+ });
13
+ }
14
+ /**
15
+ * Update the text color for all elements globally.
16
+ */
17
+ export async function serviceUpdataALLTextNodeColor(tabId, color) {
18
+ // Use "body, body *" to target all elements, with !important to override existing styles.
19
+ const css = `body, body * { color: ${color} !important; }`;
20
+ await applyGlobalCss(tabId, css);
21
+ }
22
+ /**
23
+ * Update the background color for all elements globally.
24
+ */
25
+ export async function serviceUpdataALLNodeBackgroundColor(tabId, bgColor) {
26
+ // Apply background-color to all elements.
27
+ const css = `body, body * { background-color: ${bgColor} !important; }`;
28
+ await applyGlobalCss(tabId, css);
29
+ }
30
+ /**
31
+ * Adjust font size globally by a delta value.
32
+ * Uses recursive DOM traversal to support Shadow DOM elements.
33
+ */
34
+ export async function serviceIncreaseAllTextFontSize(tabId, delta) {
35
+ await browser.scripting.executeScript({
36
+ target: { tabId },
37
+ args: [{ delta }],
38
+ func: (({ delta }) => {
39
+ /**
40
+ * Recursively traverse DOM and Shadow DOM to update font sizes.
41
+ */
42
+ function walk(root) {
43
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
44
+ let node;
45
+ while ((node = walker.nextNode())) {
46
+ const el = node;
47
+ // If the element has a Shadow Root, recurse into it to support web components.
48
+ if (el.shadowRoot) {
49
+ walk(el.shadowRoot);
50
+ }
51
+ // Calculate and update font size
52
+ const style = window.getComputedStyle(el);
53
+ const currentSize = parseFloat(style.fontSize);
54
+ if (!isNaN(currentSize)) {
55
+ el.style.setProperty('font-size', `${currentSize + delta}px`, 'important');
56
+ }
57
+ }
58
+ }
59
+ // Start traversal from the document body
60
+ walk(document.body);
61
+ }), // Cast to any to bypass strict type checking for the execution closure
62
+ });
63
+ }
package/package.json CHANGED
@@ -1,14 +1,20 @@
1
1
  {
2
2
  "name": "@vacantthinker/firefox-addon-framework-easy",
3
- "version": "2026.0611.0821",
3
+ "version": "2026.0611.1153",
4
4
  "description": "",
5
- "main": "index.js",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
6
11
  "publishConfig": {
7
12
  "access": "public",
8
13
  "provenance": true
9
14
  },
10
15
  "scripts": {
11
- "install_package": "npm install"
16
+ "install_package": "npm install",
17
+ "build": "tsc"
12
18
  },
13
19
  "author": "VacantThinker",
14
20
  "license": "AGPL-3.0-only",
@@ -20,7 +26,8 @@
20
26
  "bugs": {
21
27
  "url": "https://github.com/VacantThinker/firefox-addon-framework-easy/issues"
22
28
  },
23
- "dependencies": {
29
+ "devDependencies": {
30
+ "typescript": "6.0.3",
24
31
  "@types/firefox-webext-browser": "^143.0.0"
25
32
  }
26
33
  }
@@ -1,34 +0,0 @@
1
- # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2
- # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages
3
-
4
- name: Node.js Package
5
-
6
- on:
7
- push:
8
- branches:
9
- - main #
10
-
11
- jobs:
12
- build:
13
- runs-on: ubuntu-latest
14
- steps:
15
- - uses: actions/checkout@v6
16
- - uses: actions/setup-node@v6
17
- with:
18
- node-version: 24
19
- - run: npm ci
20
-
21
- publish-npm:
22
- needs: build
23
- runs-on: ubuntu-latest
24
- permissions:
25
- contents: read
26
- id-token: write
27
- steps:
28
- - uses: actions/checkout@v6
29
- - uses: actions/setup-node@v6
30
- with:
31
- node-version: 24
32
- registry-url: https://registry.npmjs.org/
33
- - run: npm ci
34
- - run: npm publish --provenance --access public
package/index.js DELETED
@@ -1,17 +0,0 @@
1
- export * from './src/BaseORM.js'
2
- export * from './src/browserDownload.js'
3
- export * from './src/browserNotification.js'
4
- export * from './src/browserRuntime.js'
5
- export * from './src/browserRuntimeOnMessageCommon.js'
6
- export * from './src/browserTab.js'
7
- export * from './src/DomainORM.js'
8
- export * from './src/generate.js'
9
- export * from './src/opStorage.js'
10
- export * from './src/opTab.js'
11
- export * from './src/serviceCommon.js'
12
- export * from './src/serviceFetch.js'
13
- export * from './src/serviceGet.js'
14
- export * from './src/serviceOpContent.js'
15
- export * from './src/serviceOpJavascript.js'
16
- export * from './src/servicePure.js'
17
- export * from './src/serviceUpdateTabStyle.js'
package/publish.sh DELETED
@@ -1,81 +0,0 @@
1
- #!/bin/bash
2
-
3
- # 1. Get the current time (Format example: 2026.0522.0443)
4
- # This includes the date, hour, and minute to ensure the version number increments every time you push.
5
- NEW_VERSION=$(date +'%Y.%m%d.%H%M')
6
-
7
- echo "🚀 Starting version update to: $NEW_VERSION"
8
-
9
- # 2. Use jq to automatically modify the version field in package.json and write it back
10
- jq ".version = \"$NEW_VERSION\"" package.json > package.json.tmp && mv package.json.tmp package.json
11
-
12
- # 2.5 Automatically scan all js files in the src directory and generate export statements for index.js
13
- echo "🚀 Dynamically generating index.js exports..."
14
- true > index.js
15
- for file in src/*.js; do
16
- if [ -f "$file" ]; then
17
- echo "export * from './$file'" >> index.js
18
- fi
19
- done
20
-
21
- # 2.6 Automatically reset README.md and append the scanned public functions
22
- echo "📝 Updating README.md..."
23
-
24
- # 1. Write the default fixed content
25
- cat << 'EOF' > README.md
26
- # firefox-addon-framework-easy
27
-
28
- [![License: AGPL v3](https://shields.io)](https://gnu.org)
29
-
30
- ## License
31
-
32
- This project is licensed under the GNU Affero General Public License v3.0 - see the [LICENSE](LICENSE) file for details.
33
-
34
-
35
- ## Source Code Access
36
-
37
- According to the terms of the AGPL-3.0, the source code for this network service must be made available to all users.
38
-
39
- You can download, clone, or view the complete source code for this application here: [Insert your GitHub/GitLab URL].
40
-
41
- ## API Reference (Auto-Generated)
42
-
43
- Below is a list of all public functions found inside the `src` directory:
44
-
45
- EOF
46
-
47
- # 2. Iterate through all js files, capture multi-line signatures, and append them to README
48
- for file in src/*.js; do
49
- if [ -f "$file" ]; then
50
- echo "### 📄 File: \`$file\`" >> README.md
51
- echo "\`\`\`javascript" >> README.md
52
-
53
- # Reads multi-line signatures up to the opening brace or semicolon
54
- awk '/^export (async )?(function|const|let|var|class) / {
55
- line = $0
56
- # Keep reading lines if there is no opening brace or semicolon yet
57
- while (line !~ /\{/ && line !~ /;/ && (getline next_line) > 0) {
58
- line = line "\n" next_line
59
- }
60
- # Clean up the function body and replace it with standard closing
61
- sub(/\{.*/, "{ }", line)
62
- print line
63
- print ""
64
- }' "$file" >> README.md
65
-
66
- echo "\`\`\`" >> README.md
67
- echo "" >> README.md
68
- fi
69
- done
70
-
71
- # 3. Check if there are any code changes to commit
72
- git add .
73
-
74
- # 4. Automatically commit and log this release version
75
- git commit -m "chore: bump version to $NEW_VERSION and publish"
76
-
77
- # 5. Push to GitHub to trigger cloud-based automated publishing
78
- echo "📤 Pushing to GitHub..."
79
- git push origin main
80
-
81
- echo "✅ Push complete! Please check the GitHub Actions page to view the deployment status."