browser-extension-settings 0.1.0 → 0.2.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.
- package/lib/common.ts +1 -1
- package/lib/index.ts +7 -1
- package/lib/settings.ts +144 -66
- package/lib/style.scss +5 -5
- package/lib/switch.ts +10 -2
- package/package.json +7 -3
package/lib/common.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export const besVersion =
|
|
1
|
+
export const besVersion = 15
|
|
2
2
|
export const openButton = `<svg viewBox="0 0 60.2601318359375 84.8134765625" version="1.1" xmlns="http://www.w3.org/2000/svg" class=" glyph-box" style="height: 9.62969px; width: 6.84191px;"><g transform="matrix(1 0 0 1 -6.194965820312518 77.63671875)"><path d="M66.4551-35.2539C66.4551-36.4746 65.9668-37.5977 65.0391-38.4766L26.3672-76.3672C25.4883-77.1973 24.4141-77.6367 23.1445-77.6367C20.6543-77.6367 18.7012-75.7324 18.7012-73.1934C18.7012-71.9727 19.1895-70.8496 19.9707-70.0195L55.5176-35.2539L19.9707-0.488281C19.1895 0.341797 18.7012 1.41602 18.7012 2.68555C18.7012 5.22461 20.6543 7.12891 23.1445 7.12891C24.4141 7.12891 25.4883 6.68945 26.3672 5.81055L65.0391-32.0312C65.9668-32.959 66.4551-34.0332 66.4551-35.2539Z"></path></g></svg>`
|
|
3
3
|
export const openInNewTabButton = `<svg viewBox="0 0 72.127685546875 72.2177734375" version="1.1" xmlns="http://www.w3.org/2000/svg" class=" glyph-box" style="height: 8.19958px; width: 8.18935px;"><g transform="matrix(1 0 0 1 -12.451127929687573 71.3388671875)"><path d="M84.5703-17.334L84.5215-66.4551C84.5215-69.2383 82.7148-71.1914 79.7852-71.1914L30.6641-71.1914C27.9297-71.1914 26.0742-69.0918 26.0742-66.748C26.0742-64.4043 28.1738-62.4023 30.4688-62.4023L47.4609-62.4023L71.2891-63.1836L62.207-55.2246L13.8184-6.73828C12.9395-5.85938 12.4512-4.73633 12.4512-3.66211C12.4512-1.31836 14.5508 0.878906 16.9922 0.878906C18.1152 0.878906 19.1895 0.488281 20.0684-0.439453L68.5547-48.877L76.6113-58.0078L75.7324-35.2051L75.7324-17.1387C75.7324-14.8438 77.7344-12.6953 80.127-12.6953C82.4707-12.6953 84.5703-14.6973 84.5703-17.334Z"></path></g></svg>`
|
package/lib/index.ts
CHANGED
package/lib/settings.ts
CHANGED
|
@@ -33,10 +33,14 @@ type SettingsOptions = {
|
|
|
33
33
|
footer?: string
|
|
34
34
|
settingsTable?: SettingsTable
|
|
35
35
|
onValueChange?: () => void
|
|
36
|
+
onViewUpdate?: (settingsMainView: HTMLElement) => void
|
|
36
37
|
relatedExtensions?: RelatedExtension[]
|
|
37
38
|
}
|
|
38
39
|
|
|
39
|
-
type SettingsTable = Record<
|
|
40
|
+
type SettingsTable = Record<
|
|
41
|
+
string,
|
|
42
|
+
SettingsSwitchItem | SettingsInputItem | SettingsActionItem | SettingsTipItem
|
|
43
|
+
>
|
|
40
44
|
|
|
41
45
|
type SettingsSwitchItem = {
|
|
42
46
|
title: string
|
|
@@ -53,6 +57,22 @@ type SettingsInputItem = {
|
|
|
53
57
|
group?: number
|
|
54
58
|
}
|
|
55
59
|
|
|
60
|
+
type SettingsActionItem = {
|
|
61
|
+
title: string
|
|
62
|
+
type: string
|
|
63
|
+
onclick?: () => void
|
|
64
|
+
group?: number
|
|
65
|
+
defaultValue?: any
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
type SettingsTipItem = {
|
|
69
|
+
title: string
|
|
70
|
+
type: string
|
|
71
|
+
tipContent: string
|
|
72
|
+
group?: number
|
|
73
|
+
defaultValue?: any
|
|
74
|
+
}
|
|
75
|
+
|
|
56
76
|
type RelatedExtension = {
|
|
57
77
|
id: string
|
|
58
78
|
title: string
|
|
@@ -95,6 +115,29 @@ async function saveSattingsValue(key: string, value: any) {
|
|
|
95
115
|
await setValue(storageKey, settings)
|
|
96
116
|
}
|
|
97
117
|
|
|
118
|
+
export async function resetSattingsValues() {
|
|
119
|
+
await setValue(storageKey, {})
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export async function saveSattingsValues(
|
|
123
|
+
values: Record<string, boolean | string | undefined>
|
|
124
|
+
) {
|
|
125
|
+
const settings = await getSettings()
|
|
126
|
+
|
|
127
|
+
for (const key in values) {
|
|
128
|
+
if (Object.hasOwn(values, key)) {
|
|
129
|
+
const value = values[key]
|
|
130
|
+
|
|
131
|
+
settings[key] =
|
|
132
|
+
settingsTable[key] && settingsTable[key].defaultValue === value
|
|
133
|
+
? undefined
|
|
134
|
+
: value
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
await setValue(storageKey, settings)
|
|
139
|
+
}
|
|
140
|
+
|
|
98
141
|
export function getSettingsValue(key: string): boolean | string | undefined {
|
|
99
142
|
return Object.hasOwn(settings, key)
|
|
100
143
|
? (settings[key] as boolean | string | undefined)
|
|
@@ -160,7 +203,10 @@ async function updateOptions() {
|
|
|
160
203
|
const textArea = $(
|
|
161
204
|
`#${settingsElementId} .option_groups textarea[data-key="${key}"]`
|
|
162
205
|
) as HTMLTextAreaElement
|
|
163
|
-
|
|
206
|
+
if (textArea) {
|
|
207
|
+
textArea.value = getSettingsValue(key) as string
|
|
208
|
+
}
|
|
209
|
+
|
|
164
210
|
break
|
|
165
211
|
}
|
|
166
212
|
|
|
@@ -171,14 +217,9 @@ async function updateOptions() {
|
|
|
171
217
|
}
|
|
172
218
|
}
|
|
173
219
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
group2.style.display = getSettingsValue(
|
|
178
|
-
`enableCustomRulesForCurrentSite_${host}`
|
|
179
|
-
)
|
|
180
|
-
? "block"
|
|
181
|
-
: "none"
|
|
220
|
+
if (typeof settingsOptions.onViewUpdate === "function") {
|
|
221
|
+
const settingsMain = createSettingsElement()
|
|
222
|
+
settingsOptions.onViewUpdate(settingsMain)
|
|
182
223
|
}
|
|
183
224
|
}
|
|
184
225
|
|
|
@@ -274,67 +315,77 @@ function createSettingsElement() {
|
|
|
274
315
|
const group = item.group || 1
|
|
275
316
|
const optionGroup = getOptionGroup(group)
|
|
276
317
|
// console.log(key, item, type, group)
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
})
|
|
285
|
-
|
|
286
|
-
switchOption.dataset.key = key
|
|
287
|
-
|
|
288
|
-
addElement(optionGroup, switchOption)
|
|
289
|
-
} else if (type === "textarea") {
|
|
290
|
-
let timeoutId: number | undefined
|
|
291
|
-
addElement(optionGroup, "textarea", {
|
|
292
|
-
"data-key": key,
|
|
293
|
-
placeholder: (item as SettingsInputItem).placeholder || "",
|
|
294
|
-
onkeyup(event: Event) {
|
|
295
|
-
const textArea = event.target as HTMLTextAreaElement
|
|
296
|
-
if (timeoutId) {
|
|
297
|
-
clearTimeout(timeoutId)
|
|
298
|
-
timeoutId = undefined
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
timeoutId = setTimeout(async () => {
|
|
302
|
-
if (textArea) {
|
|
303
|
-
await saveSattingsValue(key, textArea.value.trim())
|
|
318
|
+
switch (type) {
|
|
319
|
+
case "switch": {
|
|
320
|
+
const switchOption = createSwitchOption(item.title, {
|
|
321
|
+
async onchange(event: Event) {
|
|
322
|
+
const checkbox = event.target as HTMLInputElement
|
|
323
|
+
if (checkbox) {
|
|
324
|
+
await saveSattingsValue(key, checkbox.checked)
|
|
304
325
|
}
|
|
305
|
-
},
|
|
306
|
-
}
|
|
307
|
-
|
|
326
|
+
},
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
switchOption.dataset.key = key
|
|
330
|
+
|
|
331
|
+
addElement(optionGroup, switchOption)
|
|
332
|
+
|
|
333
|
+
break
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
case "textarea": {
|
|
337
|
+
let timeoutId: number | undefined
|
|
338
|
+
addElement(optionGroup, "textarea", {
|
|
339
|
+
"data-key": key,
|
|
340
|
+
placeholder: (item as SettingsInputItem).placeholder || "",
|
|
341
|
+
onkeyup(event: Event) {
|
|
342
|
+
const textArea = event.target as HTMLTextAreaElement
|
|
343
|
+
if (timeoutId) {
|
|
344
|
+
clearTimeout(timeoutId)
|
|
345
|
+
timeoutId = undefined
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
timeoutId = setTimeout(async () => {
|
|
349
|
+
if (textArea) {
|
|
350
|
+
await saveSattingsValue(key, textArea.value.trim())
|
|
351
|
+
}
|
|
352
|
+
}, 100)
|
|
353
|
+
},
|
|
354
|
+
})
|
|
355
|
+
|
|
356
|
+
break
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
case "action": {
|
|
360
|
+
addElement(optionGroup, "a", {
|
|
361
|
+
class: "action",
|
|
362
|
+
textContent: item.title,
|
|
363
|
+
onclick: (item as SettingsActionItem).onclick,
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
break
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
case "tip": {
|
|
370
|
+
const tip = addElement(optionGroup, "div", {
|
|
371
|
+
class: "bes_tip",
|
|
372
|
+
})
|
|
373
|
+
addElement(tip, "a", {
|
|
374
|
+
class: "bes_tip_anchor",
|
|
375
|
+
textContent: item.title,
|
|
376
|
+
})
|
|
377
|
+
const tipContent = addElement(tip, "div", {
|
|
378
|
+
class: "bes_tip_content",
|
|
379
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
380
|
+
innerHTML: (item as SettingsTipItem).tipContent,
|
|
381
|
+
})
|
|
382
|
+
break
|
|
383
|
+
}
|
|
384
|
+
// No default
|
|
308
385
|
}
|
|
309
386
|
}
|
|
310
387
|
}
|
|
311
388
|
|
|
312
|
-
const options2 = getOptionGroup(2)
|
|
313
|
-
|
|
314
|
-
const tip = addElement(options2, "div", {
|
|
315
|
-
class: "tip",
|
|
316
|
-
})
|
|
317
|
-
addElement(tip, "a", {
|
|
318
|
-
class: "tip_anchor",
|
|
319
|
-
textContent: "Examples",
|
|
320
|
-
})
|
|
321
|
-
const tipContent = addElement(tip, "div", {
|
|
322
|
-
class: "tip_content",
|
|
323
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
324
|
-
innerHTML: `<p>Custom rules for internal URLs, matching URLs will be opened in new tabs</p>
|
|
325
|
-
<p>
|
|
326
|
-
- One line per url pattern<br>
|
|
327
|
-
- All URLs contains '/posts' or '/users/'<br>
|
|
328
|
-
<pre>/posts/
|
|
329
|
-
/users/</pre>
|
|
330
|
-
|
|
331
|
-
- Regex is supported<br>
|
|
332
|
-
<pre>^/(posts|members)/d+</pre>
|
|
333
|
-
|
|
334
|
-
- '*' for all URLs
|
|
335
|
-
</p>`,
|
|
336
|
-
})
|
|
337
|
-
|
|
338
389
|
if (settingsOptions.footer) {
|
|
339
390
|
const footer = addElement(settingsMain, "footer")
|
|
340
391
|
footer.innerHTML =
|
|
@@ -351,6 +402,10 @@ function createSettingsElement() {
|
|
|
351
402
|
}
|
|
352
403
|
|
|
353
404
|
function addSideMenu() {
|
|
405
|
+
if (!getSettingsValue("displaySettingsButtonInSideMenu")) {
|
|
406
|
+
return
|
|
407
|
+
}
|
|
408
|
+
|
|
354
409
|
const menu =
|
|
355
410
|
$("#browser_extension_side_menu") ||
|
|
356
411
|
addElement(doc.body, "div", {
|
|
@@ -379,6 +434,27 @@ function addSideMenu() {
|
|
|
379
434
|
})
|
|
380
435
|
}
|
|
381
436
|
|
|
437
|
+
function addCommonSettings(settingsTable: SettingsTable) {
|
|
438
|
+
let maxGroup = 0
|
|
439
|
+
for (const key in settingsTable) {
|
|
440
|
+
if (Object.hasOwn(settingsTable, key)) {
|
|
441
|
+
const item = settingsTable[key]
|
|
442
|
+
const group = item.group || 1
|
|
443
|
+
if (group > maxGroup) {
|
|
444
|
+
maxGroup = group
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
settingsTable.displaySettingsButtonInSideMenu = {
|
|
450
|
+
title: "Display Settings Button in Side Menu",
|
|
451
|
+
defaultValue: !(
|
|
452
|
+
typeof GM === "object" && typeof GM.registerMenuCommand === "function"
|
|
453
|
+
),
|
|
454
|
+
group: maxGroup + 1,
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
382
458
|
export async function showSettings() {
|
|
383
459
|
const settingsContainer = getSettingsContainer()
|
|
384
460
|
|
|
@@ -395,10 +471,12 @@ export async function showSettings() {
|
|
|
395
471
|
export const initSettings = async (options: SettingsOptions) => {
|
|
396
472
|
settingsOptions = options
|
|
397
473
|
settingsTable = options.settingsTable || {}
|
|
474
|
+
addCommonSettings(settingsTable)
|
|
398
475
|
addValueChangeListener(storageKey, async () => {
|
|
399
476
|
settings = await getSettings()
|
|
400
477
|
// console.log(JSON.stringify(settings, null, 2))
|
|
401
478
|
await updateOptions()
|
|
479
|
+
addSideMenu()
|
|
402
480
|
if (typeof options.onValueChange === "function") {
|
|
403
481
|
options.onValueChange()
|
|
404
482
|
}
|
package/lib/style.scss
CHANGED
|
@@ -213,7 +213,7 @@
|
|
|
213
213
|
margin-right: 10px;
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
-
.option_groups .
|
|
216
|
+
.option_groups .bes_tip {
|
|
217
217
|
position: relative;
|
|
218
218
|
margin: 0;
|
|
219
219
|
padding: 0 15px 0 0;
|
|
@@ -221,11 +221,11 @@
|
|
|
221
221
|
max-width: none;
|
|
222
222
|
font-size: 14px;
|
|
223
223
|
|
|
224
|
-
.
|
|
224
|
+
.bes_tip_anchor {
|
|
225
225
|
cursor: help;
|
|
226
226
|
text-decoration: underline;
|
|
227
227
|
}
|
|
228
|
-
.
|
|
228
|
+
.bes_tip_content {
|
|
229
229
|
position: absolute;
|
|
230
230
|
bottom: 15px;
|
|
231
231
|
left: 0;
|
|
@@ -240,8 +240,8 @@
|
|
|
240
240
|
box-shadow: 0px 10px 39px 10px rgba(62, 66, 66, 0.22) !important;
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
-
.
|
|
244
|
-
.
|
|
243
|
+
.bes_tip_anchor:hover + .bes_tip_content,
|
|
244
|
+
.bes_tip_content:hover {
|
|
245
245
|
display: block;
|
|
246
246
|
}
|
|
247
247
|
|
package/lib/switch.ts
CHANGED
|
@@ -4,7 +4,12 @@ import {
|
|
|
4
4
|
createElement,
|
|
5
5
|
} from "browser-extension-utils"
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
type SwichOptions = {
|
|
8
|
+
checked?: boolean
|
|
9
|
+
onchange?: (event: Event) => void | Promise<void>
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function createSwitch(options = {} as SwichOptions): HTMLElement {
|
|
8
13
|
const container = createElement("label", { class: "container" })
|
|
9
14
|
const checkbox = createElement(
|
|
10
15
|
"input",
|
|
@@ -21,7 +26,10 @@ export function createSwitch(options = {}): HTMLElement {
|
|
|
21
26
|
return container
|
|
22
27
|
}
|
|
23
28
|
|
|
24
|
-
export function createSwitchOption(
|
|
29
|
+
export function createSwitchOption(
|
|
30
|
+
text: string,
|
|
31
|
+
options: SwichOptions
|
|
32
|
+
): HTMLElement {
|
|
25
33
|
const div = createElement("div", { class: "switch_option" })
|
|
26
34
|
addElement(div, "span", { textContent: text })
|
|
27
35
|
div.append(createSwitch(options))
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "browser-extension-settings",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Settings module for developing browser extensions and userscripts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"p": "prettier --write .",
|
|
9
|
-
"lint": "
|
|
9
|
+
"lint": "run-s lint:*",
|
|
10
|
+
"lint:code": "prettier --write . && xo --fix",
|
|
11
|
+
"lint:type": "tsc --noemit",
|
|
10
12
|
"test": "echo \"Error: no test specified\" && exit 0"
|
|
11
13
|
},
|
|
12
14
|
"repository": {
|
|
@@ -26,11 +28,13 @@
|
|
|
26
28
|
"homepage": "https://github.com/utags/browser-extension-settings#readme",
|
|
27
29
|
"dependencies": {
|
|
28
30
|
"browser-extension-storage": "^0.1.2",
|
|
29
|
-
"browser-extension-utils": "^0.1.
|
|
31
|
+
"browser-extension-utils": "^0.1.9"
|
|
30
32
|
},
|
|
31
33
|
"devDependencies": {
|
|
32
34
|
"@types/chrome": "^0.0.237",
|
|
35
|
+
"npm-run-all": "^4.1.5",
|
|
33
36
|
"prettier": "^2.8.8",
|
|
37
|
+
"typescript": "^5.1.6",
|
|
34
38
|
"xo": "^0.54.2"
|
|
35
39
|
},
|
|
36
40
|
"files": [
|