@vacantthinker/firefox-addon-framework-easy 2026.605.1024 → 2026.605.1200
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/.prettierrc.json +12 -0
- package/README.md +3 -3
- package/package.json +3 -17
- package/src/generate.js +201 -206
- package/src/serviceOpContent.js +55 -53
- package/src/serviceOpJavascript.js +4 -8
package/.prettierrc.json
ADDED
package/README.md
CHANGED
|
@@ -92,8 +92,8 @@ export class DomainORM extends BaseORM { }
|
|
|
92
92
|
### 📄 File: `src/generate.js`
|
|
93
93
|
```javascript
|
|
94
94
|
export function generateHtmlByUserSettings(
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
userSettings,
|
|
96
|
+
radioItemClickCallback
|
|
97
97
|
) { }
|
|
98
98
|
|
|
99
99
|
export function generateMkvScriptForSystemWindows({ }
|
|
@@ -187,7 +187,7 @@ export function serviceGetCurrentDateYYYYMMDDHHMMSS() { }
|
|
|
187
187
|
```javascript
|
|
188
188
|
export async function serviceCopyContentToClipboard(data) { }
|
|
189
189
|
|
|
190
|
-
export function serviceSaveContentToLocal(content, filename, ext =
|
|
190
|
+
export function serviceSaveContentToLocal(content, filename, ext = "txt") { }
|
|
191
191
|
|
|
192
192
|
export async function serviceGenerateMkvToolNixScript({ }
|
|
193
193
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vacantthinker/firefox-addon-framework-easy",
|
|
3
|
-
"version": "2026.0605.
|
|
3
|
+
"version": "2026.0605.1200",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"publishConfig": {
|
|
@@ -24,21 +24,7 @@
|
|
|
24
24
|
"@types/firefox-webext-browser": "^143.0.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"prettier": "3.8.3",
|
|
28
|
-
"prettier-plugin-jsdoc": "1.8.1"
|
|
29
|
-
},
|
|
30
|
-
"prettier": {
|
|
31
|
-
"semi": true,
|
|
32
|
-
"singleQuote": true,
|
|
33
|
-
"tabWidth": 2,
|
|
34
|
-
"useTabs": false,
|
|
35
|
-
"printWidth": 80,
|
|
36
|
-
"plugins": [
|
|
37
|
-
"prettier-plugin-jsdoc"
|
|
38
|
-
],
|
|
39
|
-
"jsdocVerticalizeParams": true,
|
|
40
|
-
"jsdocLineWrappingStyle": "balance",
|
|
41
|
-
"jsdocPreferToKeepShortOnOneLine": false,
|
|
42
|
-
"jsdocKeepUnpublished": false
|
|
27
|
+
"prettier": "^3.8.3",
|
|
28
|
+
"prettier-plugin-jsdoc": "^1.8.1"
|
|
43
29
|
}
|
|
44
30
|
}
|
package/src/generate.js
CHANGED
|
@@ -1,215 +1,211 @@
|
|
|
1
|
-
import {stoOpGet, stoOpSet} from
|
|
1
|
+
import { stoOpGet, stoOpSet } from "./opStorage.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Generates HTML elements based on a user settings schema object.
|
|
5
5
|
*
|
|
6
|
-
* @param
|
|
7
|
-
* @param
|
|
6
|
+
* @param {Object} userSettings
|
|
7
|
+
* @param {Function} radioItemClickCallback
|
|
8
8
|
* @returns {HTMLFieldSetElement[]}
|
|
9
9
|
*/
|
|
10
10
|
export function generateHtmlByUserSettings(
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
userSettings,
|
|
12
|
+
radioItemClickCallback
|
|
13
13
|
) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return fieldsets;
|
|
14
|
+
// Keeps track of all generated fieldsets by their storageKey
|
|
15
|
+
const elementsMap = {};
|
|
16
|
+
|
|
17
|
+
const fieldsets = Object.keys(userSettings).map((storageKey) => {
|
|
18
|
+
const storageValue = userSettings[storageKey];
|
|
19
|
+
const type = storageValue.type || "text"; // Default to text if type is not specified
|
|
20
|
+
|
|
21
|
+
// Common container wrapper for every configuration item
|
|
22
|
+
const eleWrap = document.createElement("fieldset");
|
|
23
|
+
const eleTitle = document.createElement("legend");
|
|
24
|
+
eleTitle.textContent = storageKey;
|
|
25
|
+
eleWrap.append(eleTitle);
|
|
26
|
+
|
|
27
|
+
// Save a reference to the wrapper element for visibility switching
|
|
28
|
+
elementsMap[storageKey] = eleWrap;
|
|
29
|
+
|
|
30
|
+
// --- CONDITION 1: CHECKBOX & RADIO ---
|
|
31
|
+
if (type === "checkbox" || type === "radio") {
|
|
32
|
+
/** @type {string[]} */
|
|
33
|
+
const options = storageValue.options || [];
|
|
34
|
+
|
|
35
|
+
options
|
|
36
|
+
.map((option) => {
|
|
37
|
+
const eleLabel = document.createElement("label");
|
|
38
|
+
eleLabel.textContent = option;
|
|
39
|
+
|
|
40
|
+
const eleInput = document.createElement("input");
|
|
41
|
+
eleInput.name = storageKey;
|
|
42
|
+
eleInput.type = type;
|
|
43
|
+
eleInput.value = option;
|
|
44
|
+
|
|
45
|
+
if (type === "checkbox") {
|
|
46
|
+
stoOpGet(storageKey).then((v) => {
|
|
47
|
+
const initialArray = Array.from(v || storageValue.selected || []);
|
|
48
|
+
const set = new Set(initialArray);
|
|
49
|
+
eleInput.checked = set.has(option);
|
|
50
|
+
|
|
51
|
+
// Initial visibility evaluation
|
|
52
|
+
triggerVisibility(storageKey, initialArray);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
eleInput.addEventListener("change", async () => {
|
|
56
|
+
const optionsCurrent =
|
|
57
|
+
(await stoOpGet(storageKey)) || storageValue.selected || [];
|
|
58
|
+
const set = new Set(Array.from(optionsCurrent));
|
|
59
|
+
|
|
60
|
+
if (eleInput.checked) {
|
|
61
|
+
set.add(option);
|
|
62
|
+
} else {
|
|
63
|
+
set.delete(option);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const valueNew = Array.from(set);
|
|
67
|
+
await stoOpSet(storageKey, valueNew);
|
|
68
|
+
|
|
69
|
+
// Dynamic visibility update
|
|
70
|
+
triggerVisibility(storageKey, valueNew);
|
|
71
|
+
});
|
|
72
|
+
} else if (type === "radio") {
|
|
73
|
+
stoOpGet(storageKey).then((v) => {
|
|
74
|
+
const currentSelected =
|
|
75
|
+
v !== undefined && v !== null ? v : storageValue.selected;
|
|
76
|
+
if (option === currentSelected) {
|
|
77
|
+
eleInput.checked = true;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Initial visibility evaluation
|
|
81
|
+
triggerVisibility(storageKey, currentSelected);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
eleLabel.onclick = function () {
|
|
85
|
+
stoOpSet(storageKey, option).then(() => {
|
|
86
|
+
if (typeof radioItemClickCallback === "function") {
|
|
87
|
+
radioItemClickCallback(storageKey, option);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Dynamic visibility update
|
|
91
|
+
triggerVisibility(storageKey, option);
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
eleLabel.append(eleInput);
|
|
97
|
+
return eleLabel;
|
|
98
|
+
})
|
|
99
|
+
.forEach((ele) => eleWrap.append(ele));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// --- CONDITION 2: TOGGLE BUTTON ---
|
|
103
|
+
else if (type === "button") {
|
|
104
|
+
const eleButton = document.createElement("button");
|
|
105
|
+
eleButton.type = "button"; // Prevent accidental form submissions
|
|
106
|
+
|
|
107
|
+
stoOpGet(storageKey).then((v) => {
|
|
108
|
+
// Fallback to default schema configuration if no value is stored yet
|
|
109
|
+
let currentStatus =
|
|
110
|
+
v !== undefined && v !== null
|
|
111
|
+
? v === true || v === "true"
|
|
112
|
+
: storageValue.selected;
|
|
113
|
+
eleButton.textContent = String(currentStatus);
|
|
114
|
+
|
|
115
|
+
// Initial visibility evaluation
|
|
116
|
+
triggerVisibility(storageKey, currentStatus);
|
|
117
|
+
|
|
118
|
+
eleButton.addEventListener("click", async () => {
|
|
119
|
+
currentStatus = !currentStatus; // Toggle state
|
|
120
|
+
eleButton.textContent = String(currentStatus);
|
|
121
|
+
await stoOpSet(storageKey, currentStatus);
|
|
122
|
+
|
|
123
|
+
// Dynamic visibility update
|
|
124
|
+
triggerVisibility(storageKey, currentStatus);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
eleWrap.append(eleButton);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// --- CONDITION 3: NUMBER & TEXT INPUTS ---
|
|
132
|
+
else if (type === "number" || type === "text") {
|
|
133
|
+
const eleInput = document.createElement("input");
|
|
134
|
+
eleInput.type = type;
|
|
135
|
+
eleInput.name = storageKey;
|
|
136
|
+
|
|
137
|
+
stoOpGet(storageKey).then((v) => {
|
|
138
|
+
const currentVal =
|
|
139
|
+
v !== undefined && v !== null ? v : storageValue.selected;
|
|
140
|
+
eleInput.value = currentVal;
|
|
141
|
+
|
|
142
|
+
// Initial visibility evaluation
|
|
143
|
+
triggerVisibility(storageKey, currentVal);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Updates storage on every keystroke/change execution
|
|
147
|
+
eleInput.addEventListener("input", async () => {
|
|
148
|
+
const rawValue = eleInput.value;
|
|
149
|
+
const finalizedValue = type === "number" ? Number(rawValue) : rawValue;
|
|
150
|
+
|
|
151
|
+
await stoOpSet(storageKey, finalizedValue);
|
|
152
|
+
|
|
153
|
+
// Dynamic visibility update
|
|
154
|
+
triggerVisibility(storageKey, finalizedValue);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
eleWrap.append(eleInput);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// --- CONDITION 4: SPAN / READ-ONLY TEXT ---
|
|
161
|
+
else if (type === "span") {
|
|
162
|
+
const eleSpan = document.createElement("span");
|
|
163
|
+
// Optional: Add a class for styling read-only text differently
|
|
164
|
+
// eleSpan.className = 'read-only-text';
|
|
165
|
+
|
|
166
|
+
stoOpGet(storageKey).then((v) => {
|
|
167
|
+
// Fallback to default schema configuration if no value is stored yet
|
|
168
|
+
const currentVal =
|
|
169
|
+
v !== undefined && v !== null ? v : storageValue.selected;
|
|
170
|
+
|
|
171
|
+
// Render as plain text
|
|
172
|
+
eleSpan.textContent = String(currentVal);
|
|
173
|
+
|
|
174
|
+
// Initial visibility evaluation
|
|
175
|
+
triggerVisibility(storageKey, currentVal);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
eleWrap.append(eleSpan);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return eleWrap;
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Evaluates the visibility rules for a given source key based on its current
|
|
186
|
+
* value.
|
|
187
|
+
*/
|
|
188
|
+
function triggerVisibility(sourceKey, currentValue) {
|
|
189
|
+
const config = userSettings[sourceKey];
|
|
190
|
+
if (config && config.visibilityControl) {
|
|
191
|
+
const { targetField, expectedValue } = config.visibilityControl;
|
|
192
|
+
const targetElement = elementsMap[targetField];
|
|
193
|
+
|
|
194
|
+
if (targetElement) {
|
|
195
|
+
// String conversion guarantees type safety (e.g., matching boolean true against string "true")
|
|
196
|
+
const shouldBeVisible = String(currentValue) === String(expectedValue);
|
|
197
|
+
targetElement.style.display = shouldBeVisible ? "" : "none";
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return fieldsets;
|
|
207
203
|
}
|
|
208
204
|
|
|
209
|
-
export function generateMkvScriptForSystemWindows({vid, title}) {
|
|
210
|
-
|
|
205
|
+
export function generateMkvScriptForSystemWindows({ vid, title }) {
|
|
206
|
+
let args = { vid, title };
|
|
211
207
|
|
|
212
|
-
|
|
208
|
+
return `if (true) {
|
|
213
209
|
const path = require('path');
|
|
214
210
|
const fs = require('fs');
|
|
215
211
|
const {execSync, exec} = require('node:child_process');
|
|
@@ -294,11 +290,11 @@ export function generateMkvScriptForSystemWindows({vid, title}) {
|
|
|
294
290
|
`;
|
|
295
291
|
}
|
|
296
292
|
|
|
297
|
-
export function generateMkvScriptForSystemFedora({vid, title}) {
|
|
298
|
-
|
|
293
|
+
export function generateMkvScriptForSystemFedora({ vid, title }) {
|
|
294
|
+
let args = { vid, title };
|
|
299
295
|
|
|
300
|
-
|
|
301
|
-
|
|
296
|
+
// We wrap the Node.js script inside a Linux Shell script block
|
|
297
|
+
return `#!/usr/bin/env bash
|
|
302
298
|
# This header tells Fedora to treat this file as a runnable bash script
|
|
303
299
|
|
|
304
300
|
# Open a terminal window if not already running inside one
|
|
@@ -373,4 +369,3 @@ read unused_input
|
|
|
373
369
|
rm -- "$0"
|
|
374
370
|
`;
|
|
375
371
|
}
|
|
376
|
-
|
package/src/serviceOpContent.js
CHANGED
|
@@ -1,80 +1,82 @@
|
|
|
1
|
-
import {browserRuntimePlatformInfo} from
|
|
2
|
-
import {
|
|
1
|
+
import { browserRuntimePlatformInfo } from "./browserRuntime.js";
|
|
2
|
+
import {
|
|
3
|
+
generateMkvScriptForSystemFedora,
|
|
4
|
+
generateMkvScriptForSystemWindows
|
|
5
|
+
} from "./generate.js";
|
|
3
6
|
|
|
4
7
|
/**
|
|
5
|
-
*
|
|
6
|
-
* @param data
|
|
8
|
+
* @param data
|
|
7
9
|
* @returns {Promise<void>}
|
|
8
10
|
*/
|
|
9
11
|
export async function serviceCopyContentToClipboard(data) {
|
|
10
|
-
|
|
12
|
+
return await window.navigator.clipboard.writeText(data);
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
|
-
*
|
|
16
|
+
* Eg: fnName('this is content', 'this is a filename without ext', 'txt')
|
|
17
|
+
*
|
|
15
18
|
* @param {string} content
|
|
16
|
-
* @param {string} filename
|
|
17
|
-
* @param {string} ext
|
|
19
|
+
* @param {string} filename Eg: abc
|
|
20
|
+
* @param {string} ext Txt json
|
|
18
21
|
*/
|
|
19
|
-
export function serviceSaveContentToLocal(content, filename, ext =
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
export function serviceSaveContentToLocal(content, filename, ext = "txt") {
|
|
23
|
+
const eleBtn = document.createElement("button");
|
|
24
|
+
eleBtn.addEventListener(
|
|
25
|
+
"click",
|
|
26
|
+
function () {
|
|
27
|
+
const eleA = document.createElement("a");
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
const extObj = {
|
|
30
|
+
txt: "text/plain",
|
|
31
|
+
json: "application/json"
|
|
32
|
+
};
|
|
33
|
+
const type = extObj[ext];
|
|
31
34
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
const file = new Blob([content], { type });
|
|
36
|
+
eleA.href = URL.createObjectURL(file);
|
|
37
|
+
eleA.download = [filename, ext].join(".");
|
|
38
|
+
eleA.click();
|
|
39
|
+
URL.revokeObjectURL(eleA.href);
|
|
40
|
+
},
|
|
41
|
+
false
|
|
42
|
+
);
|
|
43
|
+
eleBtn.click();
|
|
44
|
+
// eleBtn.previousElementSibling
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
48
|
+
* Need install nodejs mkvtoolnix
|
|
49
|
+
*
|
|
50
|
+
* @param message{{ Vid, title,
|
|
51
|
+
* }}
|
|
49
52
|
* @returns {Promise<void>}
|
|
50
53
|
*/
|
|
51
|
-
export async function serviceGenerateMkvToolNixScript({vid, title}) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
54
|
+
export async function serviceGenerateMkvToolNixScript({ vid, title }) {
|
|
55
|
+
let message = { vid, title };
|
|
56
|
+
const platformInfo = await browserRuntimePlatformInfo();
|
|
57
|
+
if (platformInfo.os === "win") {
|
|
58
|
+
let content = generateMkvScriptForSystemWindows(message);
|
|
59
|
+
serviceSaveContentToLocal(content, title, "js");
|
|
60
|
+
} else if (platformInfo.os === "linux") {
|
|
61
|
+
let content = generateMkvScriptForSystemFedora(message);
|
|
62
|
+
serviceSaveContentToLocal(content, title, "sh");
|
|
63
|
+
}
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
/**
|
|
65
|
-
* @param
|
|
66
|
-
* @returns {string}
|
|
67
|
+
* @param {string} value -
|
|
68
|
+
* @returns {string} -
|
|
67
69
|
*/
|
|
68
70
|
export function serviceRemoveIllegalWord(value) {
|
|
69
|
-
|
|
71
|
+
if (!value) return "";
|
|
70
72
|
|
|
71
|
-
|
|
73
|
+
let name = value.trim().split(/\r?\n/).shift();
|
|
72
74
|
|
|
73
|
-
|
|
75
|
+
name = name.replace(/[\p{P}\p{S}\p{C}]/gu, " ");
|
|
74
76
|
|
|
75
|
-
|
|
77
|
+
name = name.replace(/[~"#%&*:<>?/\\{|}]/g, " ");
|
|
76
78
|
|
|
77
|
-
|
|
79
|
+
name = name.replace(/[\s\u3000]+/g, " ").trim();
|
|
78
80
|
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
+
return name.replace(/^[-.]+|[-.]+$/g, "");
|
|
82
|
+
}
|
|
@@ -109,8 +109,7 @@ export async function serviceElementPicker(message) {
|
|
|
109
109
|
selector += '#' + el.id;
|
|
110
110
|
path.unshift(selector);
|
|
111
111
|
break;
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
112
|
+
} else {
|
|
114
113
|
let sib = el, nth = 1;
|
|
115
114
|
while (sib = sib.previousElementSibling) {
|
|
116
115
|
if (sib.nodeName.toLowerCase() === selector) nth++;
|
|
@@ -330,16 +329,13 @@ export async function serviceDealWithMagnetLink(message) {
|
|
|
330
329
|
|
|
331
330
|
if (handleOption === 'clipboard') {
|
|
332
331
|
await serviceCopyContentToClipboard(content);
|
|
333
|
-
}
|
|
334
|
-
else if (handleOption === 'txt') {
|
|
332
|
+
} else if (handleOption === 'txt') {
|
|
335
333
|
serviceSaveContentToLocal(content, filename);
|
|
336
|
-
}
|
|
337
|
-
else if (handleOption === 'clipboardAndTxt') {
|
|
334
|
+
} else if (handleOption === 'clipboardAndTxt') {
|
|
338
335
|
await serviceCopyContentToClipboard(content);
|
|
339
336
|
serviceSaveContentToLocal(content, filename);
|
|
340
337
|
}
|
|
341
|
-
}
|
|
342
|
-
else {
|
|
338
|
+
} else {
|
|
343
339
|
// todo notification => magnet link not found!
|
|
344
340
|
await browserNotificationCreate('magnet link not found!');
|
|
345
341
|
}
|