browser-extension-settings 0.1.0 → 0.2.0

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 CHANGED
@@ -1,3 +1,3 @@
1
- export const besVersion = 14
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
@@ -1 +1,7 @@
1
- export { initSettings, showSettings, getSettingsValue } from "./settings"
1
+ export {
2
+ initSettings,
3
+ showSettings,
4
+ getSettingsValue,
5
+ saveSattingsValues,
6
+ resetSattingsValues,
7
+ } from "./settings"
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<string, SettingsSwitchItem | SettingsInputItem>
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
- textArea.value = getSettingsValue(key) as string
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
- const host = location.host
175
- const group2 = $(`#${settingsElementId} .option_groups:nth-of-type(2)`)
176
- if (group2) {
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
- if (type === "switch") {
278
- const switchOption = createSwitchOption(item.title, {
279
- async onchange(event: Event) {
280
- if (event.target) {
281
- await saveSattingsValue(key, event.target.checked)
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)
325
+ }
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
304
346
  }
305
- }, 100)
306
- },
307
- })
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 =
package/lib/style.scss CHANGED
@@ -213,7 +213,7 @@
213
213
  margin-right: 10px;
214
214
  }
215
215
 
216
- .option_groups .tip {
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
- .tip_anchor {
224
+ .bes_tip_anchor {
225
225
  cursor: help;
226
226
  text-decoration: underline;
227
227
  }
228
- .tip_content {
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
- .tip_anchor:hover + .tip_content,
244
- .tip_content:hover {
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
- export function createSwitch(options = {}): HTMLElement {
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(text: string, options): HTMLElement {
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.0",
3
+ "version": "0.2.0",
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": "prettier --write . && xo --fix",
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": {
@@ -30,7 +32,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": [