@kudoai/chatgpt.js 3.5.0 → 3.6.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.
Files changed (37) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +147 -88
  3. package/chatgpt.js +127 -103
  4. package/dist/chatgpt.min.js +28 -4
  5. package/docs/README.md +154 -88
  6. package/docs/SECURITY.md +15 -15
  7. package/docs/USERGUIDE.md +19 -5
  8. package/package.json +10 -6
  9. package/starters/chrome/LICENSE.md +3 -3
  10. package/starters/chrome/docs/README.md +5 -5
  11. package/starters/chrome/docs/SECURITY.md +3 -5
  12. package/starters/chrome/extension/components/icons.js +2 -5
  13. package/starters/chrome/extension/components/modals.js +90 -87
  14. package/starters/chrome/extension/content.js +18 -11
  15. package/starters/chrome/extension/icons/faded/icon128.png +0 -0
  16. package/starters/chrome/extension/icons/faded/icon16.png +0 -0
  17. package/starters/chrome/extension/icons/faded/icon32.png +0 -0
  18. package/starters/chrome/extension/icons/faded/icon64.png +0 -0
  19. package/starters/chrome/extension/lib/chatgpt.js +127 -103
  20. package/starters/chrome/extension/lib/dom.js +90 -16
  21. package/starters/chrome/extension/lib/settings.js +7 -8
  22. package/starters/chrome/extension/manifest.json +1 -1
  23. package/starters/chrome/extension/popup/controller.js +7 -7
  24. package/starters/chrome/extension/popup/index.html +1 -1
  25. package/starters/chrome/extension/popup/style.css +3 -4
  26. package/starters/chrome/extension/service-worker.js +1 -1
  27. package/starters/chrome/images/icons/question-mark/icon16.png +0 -0
  28. package/starters/chrome/images/icons/question-mark/icon512.png +0 -0
  29. package/starters/docs/LICENSE.md +21 -1
  30. package/starters/docs/README.md +19 -6
  31. package/starters/greasemonkey/LICENSE.md +3 -3
  32. package/starters/greasemonkey/chatgpt.js-greasemonkey-starter.user.js +5 -6
  33. package/starters/greasemonkey/docs/README.md +1 -1
  34. package/starters/greasemonkey/docs/SECURITY.md +3 -5
  35. /package/starters/greasemonkey/{media → assets}/images/icons/robot/icon48.png +0 -0
  36. /package/starters/greasemonkey/{media → assets}/images/icons/robot/icon64.png +0 -0
  37. /package/starters/greasemonkey/{media → assets}/images/screenshots/chatgpt-userscript-on.png +0 -0
package/docs/USERGUIDE.md CHANGED
@@ -1,8 +1,8 @@
1
1
  <div align="center">
2
2
 
3
3
  <picture>
4
- <source type="image/png" media="(prefers-color-scheme: dark)" srcset="https://media.chatgptjs.org/images/logos/chatgpt.js/with-reflection/darkmode.png?bc68d0c">
5
- <img width=700 src="https://media.chatgptjs.org/images/logos/chatgpt.js/with-reflection/lightmode.png?bc68d0c">
4
+ <source type="image/png" media="(prefers-color-scheme: dark)" srcset="https://assets.chatgptjs.org/images/logos/chatgpt.js/with-reflection/darkmode.png?v=e638eac">
5
+ <img width=700 src="https://assets.chatgptjs.org/images/logos/chatgpt.js/with-reflection/lightmode.png?v=e638eac">
6
6
  </picture>
7
7
 
8
8
  **chatgpt.js** is a powerful JavaScript library that allows for super easy interaction w/ the ChatGPT DOM.
@@ -58,6 +58,7 @@
58
58
  - [getResponseFromAPI `async`](#getresponsefromapi-async)
59
59
  - [getResponseFromDOM](#getresponsefromdom)
60
60
  - [isIdle `async`](#isidle-async)
61
+ - [isTyping](#istyping)
61
62
  - [regenerate](#regenerate)
62
63
  - [resend `async`](#resend-async)
63
64
  - [scrollToBottom](#scrolltobottom)
@@ -159,7 +160,7 @@
159
160
 
160
161
  ```js
161
162
  (async () => {
162
- await import('https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.5.0/dist/chatgpt.min.js');
163
+ await import('https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.6.1/dist/chatgpt.min.js');
163
164
  // Your code here...
164
165
  })();
165
166
  ```
@@ -168,7 +169,7 @@
168
169
 
169
170
  ```js
170
171
  var xhr = new XMLHttpRequest();
171
- xhr.open('GET', 'https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.5.0/dist/chatgpt.min.js');
172
+ xhr.open('GET', 'https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.6.1/dist/chatgpt.min.js');
172
173
  xhr.onload = function () {
173
174
  if (xhr.status === 200) {
174
175
  var chatgptJS = document.createElement('script');
@@ -190,7 +191,7 @@ function yourCode() {
190
191
 
191
192
  ```js
192
193
  ...
193
- // @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.5.0/dist/chatgpt.min.js
194
+ // @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.6.1/dist/chatgpt.min.js
194
195
  // ==/UserScript==
195
196
 
196
197
  // Your code here...
@@ -929,6 +930,18 @@ Example code:
929
930
  })();
930
931
  ```
931
932
 
933
+ ### isTyping
934
+
935
+ Returns a boolean value. `true` if ChatGPT is generating a response, `false` otherwise.
936
+
937
+ Example code:
938
+
939
+ ```js
940
+ console.log(`ChatGPT is ${!chatgpt.isTyping() ? 'not' : ''} typing`)
941
+ ```
942
+
943
+ ###### _See also: [`isIdle`](#isidle-async)_
944
+
932
945
  ### regenerate
933
946
 
934
947
  Regenerates ChatGPT's response.
@@ -1023,6 +1036,7 @@ Available options:
1023
1036
  - `voice`: A number representing the index of voices available on the user device.
1024
1037
  - `pitch`: A float representing the pitch of the speech. From `0` to `2`.
1025
1038
  - `speed`: A float representing the speed of the speech. From `0.1` to `10`.
1039
+ - `onend`: A callback function invoked when speech finishes playing.
1026
1040
 
1027
1041
  Example code:
1028
1042
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kudoai/chatgpt.js",
3
- "version": "3.5.0",
3
+ "version": "3.6.1",
4
4
  "description": "Client-side JavaScript library for ChatGPT",
5
5
  "author": {
6
6
  "name": "KudoAI & contributors",
@@ -67,15 +67,19 @@
67
67
  "bugs": "https://github.com/KudoAI/chatgpt.js/issues",
68
68
  "devDependencies": {
69
69
  "@adamlui/minify.js": "^1.8.5",
70
- "@adamlui/scss-to-css": "^1.10.22",
71
- "@eslint/json": "^0.9.0",
72
- "@eslint/markdown": "^6.2.1",
73
- "@stylistic/eslint-plugin-js": "^2.12.1",
70
+ "@adamlui/scss-to-css": "^1.10.25",
71
+ "@eslint/css": "^0.2.0",
72
+ "@eslint/json": "^0.10.0",
73
+ "@eslint/markdown": "^6.2.2",
74
+ "@html-eslint/eslint-plugin": "^0.34.0",
75
+ "@html-eslint/parser": "^0.34.0",
76
+ "@stylistic/eslint-plugin-js": "^3.1.0",
74
77
  "docsify-cli": "^4.4.4",
75
- "eslint": "^9.17.0",
78
+ "eslint": "^9.20.0",
76
79
  "eslint-plugin-import": "^2.31.0",
77
80
  "eslint-plugin-regexp": "^2.7.0",
78
81
  "eslint-plugin-yml": "^1.16.0",
82
+ "get-port": "^7.1.0",
79
83
  "husky": "^9.1.7"
80
84
  }
81
85
  }
@@ -1,8 +1,8 @@
1
1
  <div align="center">
2
2
  <h6>
3
3
  <picture>
4
- <source type="image/svg+xml" media="(prefers-color-scheme: dark)" srcset="https://media.chatgptjs.org/images/icons/earth-americas-white-icon32.svg?main">
5
- <img height=14 src="https://media.chatgptjs.org/images/icons/earth-americas-icon32.svg?main">
4
+ <source type="image/svg+xml" media="(prefers-color-scheme: dark)" srcset="https://assets.chatgptjs.org/images/icons/earth/white/icon32.svg?v=e638eac">
5
+ <img height=14 src="https://assets.chatgptjs.org/images/icons/earth/black/icon32.svg?v=e638eac">
6
6
  </picture>
7
7
  &nbsp;English |
8
8
  <a href="docs/zh-cn/LICENSE.md">简体中文</a> |
@@ -22,7 +22,7 @@
22
22
 
23
23
  # 🏛️ MIT License
24
24
 
25
- **Copyright © 2023–2024 [KudoAI](https://github.com/KudoAI) & contributors**
25
+ **Copyright © 2023–2025 [KudoAI](https://github.com/KudoAI) & contributors**
26
26
 
27
27
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
28
28
 
@@ -3,8 +3,8 @@
3
3
  <div align="center">
4
4
  <h6>
5
5
  <picture>
6
- <source type="image/svg+xml" media="(prefers-color-scheme: dark)" srcset="https://media.chatgptjs.org/images/icons/earth-americas-white-icon32.svg?main">
7
- <img height=14 src="https://media.chatgptjs.org/images/icons/earth-americas-icon32.svg?main">
6
+ <source type="image/svg+xml" media="(prefers-color-scheme: dark)" srcset="https://assets.chatgptjs.org/images/icons/earth/white/icon32.svg?v=e638eac">
7
+ <img height=14 src="https://assets.chatgptjs.org/images/icons/earth/black/icon32.svg?v=e638eac">
8
8
  </picture>
9
9
  &nbsp;English |
10
10
  <a href="zh-cn#readme">简体中文</a> |
@@ -22,7 +22,7 @@
22
22
  </h6>
23
23
  </div>
24
24
 
25
- # <img height=21 src="https://media.chatgptjs.org/images/icons/platforms/chrome/icon32.png?8c852fa5"> chatgpt.js-chrome-starter
25
+ # <img height=21 src="https://assets.chatgptjs.org/images/icons/platforms/chrome/icon32.png?v=e638eac"> chatgpt.js-chrome-starter
26
26
 
27
27
  <h3>A starting point for developing your own Chrome extension using <a href="https://github.com/KudoAI/chatgpt.js">chatgpt.js</a></h3>
28
28
 
@@ -81,13 +81,13 @@ These are some of the extensions featured by Google that use chatgpt.js:
81
81
 
82
82
 
83
83
  <a href="https://chatgptinfinity.com" target="_blank" rel="noopener">
84
- <img width=777 src="https://cdn.jsdelivr.net/gh/adamlui/chatgpt-infinity@0f48c4e/chrome/media/images/tiles/marquee-promo-tile-1400x560.png">
84
+ <img width=777 src="https://assets.chatgptinfinity.com/images/tiles/marquee/tile-1400x560.png?v=34b428b">
85
85
  </a>
86
86
 
87
87
  <p><br>
88
88
 
89
89
  <a href="https://chatgptwidescreen.com" target="_blank" rel="noopener">
90
- <img width=777 src="https://cdn.jsdelivr.net/gh/adamlui/chatgpt-widescreen@3ed0950/chrome/media/images/tiles/marquee-promo-tile-1400x560.png">
90
+ <img width=777 src="https://assets.chatgptwidescreen.com/images/tiles/marquee/tile-1400x560.png?v=4c5d018">
91
91
  </a>
92
92
 
93
93
  </div>
@@ -1,8 +1,8 @@
1
1
  <div align="right">
2
2
  <h6>
3
3
  <picture>
4
- <source type="image/svg+xml" media="(prefers-color-scheme: dark)" srcset="https://media.chatgptjs.org/images/icons/earth-americas-white-icon32.svg?main">
5
- <img height=14 src="https://media.chatgptjs.org/images/icons/earth-americas-icon32.svg?main">
4
+ <source type="image/svg+xml" media="(prefers-color-scheme: dark)" srcset="https://assets.chatgptjs.org/images/icons/earth/white/icon32.svg?v=e638eac">
5
+ <img height=14 src="https://assets.chatgptjs.org/images/icons/earth/black/icon32.svg?v=e638eac">
6
6
  </picture>
7
7
  &nbsp;English |
8
8
  <a href="https://github.com/KudoAI/chatgpt.js-chrome-starter/blob/main/docs/zh-cn/SECURITY.md">简体中文</a> |
@@ -12,6 +12,4 @@
12
12
 
13
13
  # 🛡️ Security Policy
14
14
 
15
- If you find a vulnerability, please open a [draft security advisory](https://github.com/KudoAI/chatgpt.js-chrome-starter/security/advisories/new).
16
-
17
- Pull requests are also welcome, but for safety reasons, send an email to <security@kudoai.com> and wait for a response before making it public.
15
+ If you find a vulnerability, please follow the reporting instructions @ https://tidelift.com/security
@@ -1,10 +1,7 @@
1
- // Requires lib/dom.js
1
+ // Requires lib/dom.js + app
2
2
 
3
3
  window.icons = {
4
- imports: {
5
- import(deps) { // { app }
6
- for (const depName in deps) this[depName] = deps[depName] }
7
- },
4
+ import(deps) { Object.assign(this.imports = this.imports || {}, deps) },
8
5
 
9
6
  create({ name, size = 16, width, height, ...additionalAttrs }) {
10
7
  const iconData = icons[name],
@@ -1,33 +1,104 @@
1
- // Requires lib/chatgpt.js + lib/dom.js
1
+ // Requires lib/chatgpt.js + lib/dom.js + app + env
2
2
 
3
3
  window.modals = {
4
+ import(deps) { Object.assign(this.imports = this.imports || {}, deps) },
5
+
4
6
  stack: [], // of types of undismissed modals
5
7
  get class() { return `${this.imports.app.cssPrefix}-modal` },
6
8
 
7
- imports: {
8
- import(deps) { // { app, env }
9
- for (const depName in deps) this[depName] = deps[depName] }
9
+ about() {
10
+
11
+ // Show modal
12
+ const aboutModal = this.alert(
13
+ `${this.imports.app.symbol} ${chrome.runtime.getManifest().name}`, // title
14
+ '🧠 Author: ' // msg
15
+ + `<a href="${this.imports.app.author.url}">${this.imports.app.author.name}</a> `
16
+ + `& <a href="${this.imports.app.urls.contributors}">contributors</a>\n`
17
+ + `🏷️ Version: <span class="about-em">${this.imports.app.version}</span>\n`
18
+ + '📜 Open source code: '
19
+ + `<a href="${this.imports.app.urls.gitHub}" target="_blank" rel="nopener">`
20
+ + this.imports.app.urls.gitHub + '</a>\n'
21
+ + '⚡ Powered by: '
22
+ + `<a href="${this.imports.app.urls.chatgptJS}" target="_blank" rel="noopener">chatgpt.js</a>`,
23
+ [ function getSupport(){}, function rateUs(){}, function moreAiExtensions(){} ], // button labels
24
+ '', 656 // modal width
25
+ )
26
+
27
+ // Format text
28
+ aboutModal.querySelector('h2').style.cssText = (
29
+ 'text-align: center ; font-size: 51px ; line-height: 46px ; padding: 15px 0' )
30
+ aboutModal.querySelector('p').style.cssText = (
31
+ 'text-align: center ; overflow-wrap: anywhere ;'
32
+ + `margin: ${ this.imports.env.browser.isPortrait ? '6px 0 -16px' : '3px 0 0' }` )
33
+
34
+ // Hack buttons
35
+ aboutModal.querySelector('.modal-buttons').style.justifyContent = 'center'
36
+ aboutModal.querySelectorAll('button').forEach(btn => {
37
+ btn.style.cssText = 'height: 55px ; min-width: 136px ; text-align: center'
38
+
39
+ // Replace buttons w/ clones that don't dismiss modal
40
+ const btnClone = btn.cloneNode(true)
41
+ btn.parentNode.replaceChild(btnClone, btn) ; btn = btnClone
42
+ btn.onclick = () => this.safeWinOpen(
43
+ btn.textContent == 'Get Support' ? `${modals.imports.app.urls.gitHub}/issues`
44
+ : btn.textContent == 'Rate Us' ? `${modals.imports.app.urls.gitHub}/discussions`
45
+ : modals.imports.app.urls.relatedExtensions
46
+ )
47
+
48
+ // Prepend emoji
49
+ if (/support/i.test(btn.textContent))
50
+ btn.textContent = '🧠 ' + btn.textContent
51
+ else if (/rate/i.test(btn.textContent))
52
+ btn.textContent = '⭐ ' + btn.textContent
53
+ else if (/extensions/i.test(btn.textContent))
54
+ btn.textContent = '🧠 ' + btn.textContent
55
+
56
+ // Hide Dismiss button
57
+ else btn.style.display = 'none'
58
+ })
59
+
60
+ return aboutModal
10
61
  },
11
62
 
12
63
  alert(title = '', msg = '', btns = '', checkbox = '', width = '') { // generic one from chatgpt.alert()
13
64
  const alertID = chatgpt.alert(title, msg, btns, checkbox, width),
14
65
  alert = document.getElementById(alertID).firstChild
15
- this.init(alert) // add classes + starry bg
66
+ this.init(alert) // add classes + rising particles bg
16
67
  return alert
17
68
  },
18
69
 
70
+ init(modal) {
71
+ if (!modal) return // to support non-div this.open()s
72
+ if (!this.styles) this.stylize() // to init/append stylesheet
73
+ modal.classList.add('no-user-select', this.class) ; modal.parentNode.classList.add(`${this.class}-bg`)
74
+ dom.addRisingParticles(modal)
75
+ },
76
+
77
+ observeRemoval(modal, modalType) { // to maintain stack for proper nav
78
+ const modalBG = modal.parentNode
79
+ new MutationObserver(([mutation], obs) => {
80
+ mutation.removedNodes.forEach(removedNode => { if (removedNode == modalBG) {
81
+ if (this.stack[0] == modalType) { // new modal not launched, implement nav back logic
82
+ this.stack.shift() // remove this modal type from stack 1st
83
+ const prevModalType = this.stack[0]
84
+ if (prevModalType) { // open it
85
+ this.stack.shift() // remove type from stack since re-added on open
86
+ this.open(prevModalType)
87
+ }
88
+ }
89
+ obs.disconnect()
90
+ }})
91
+ }).observe(modalBG.parentNode, { childList: true, subtree: true })
92
+ },
93
+
19
94
  open(modalType) {
20
95
  const modal = this[modalType]() // show modal
21
96
  this.stack.unshift(modalType) // add to stack
22
- this.init(alert) // add classes + starry bg
97
+ this.init(modal) // add classes + rising particles bg
23
98
  this.observeRemoval(modal, modalType) // to maintain stack for proper nav
24
99
  },
25
100
 
26
- init(modal) {
27
- if (!this.styles) this.stylize() // to init/append stylesheet
28
- modal.classList.add(this.class) ; modal.parentNode.classList.add(`${this.class}-bg`) // add classes
29
- dom.fillStarryBG(modal) // add starry bg
30
- },
101
+ safeWinOpen(url) { open(url, '_blank', 'noopener') }, // to prevent backdoor vulnerabilities
31
102
 
32
103
  stylize() {
33
104
  if (!this.styles) {
@@ -35,7 +106,9 @@ window.modals = {
35
106
  document.head.append(this.styles)
36
107
  }
37
108
  this.styles.innerText = (
38
- `.${this.class} {` // modals
109
+ `.no-user-select {
110
+ user-select: none ; -webkit-user-select: none ; -moz-user-select: none ; -ms-user-select: none }`
111
+ + `.${this.class} {` // modals
39
112
  + 'font-family: -apple-system, system-ui, BlinkMacSystemFont, Segoe UI, Roboto,'
40
113
  + 'Oxygen-Sans, Ubuntu, Cantarell, Helvetica Neue, sans-serif ;'
41
114
  + 'padding: 20px 25px 24px 25px !important ; font-size: 20px ;'
@@ -58,9 +131,12 @@ window.modals = {
58
131
  + `color: #${ this.imports.env.ui.scheme == 'dark' ? '00cfff' : '1e9ebb' } !important }`
59
132
  + `.${this.class} h2 { font-weight: bold }`
60
133
  + `.${this.class} button {`
134
+ + '--btn-transition: transform 0.1s ease-in-out, box-shadow 0.1s ease-in-out ;'
61
135
  + 'font-size: 14px ; text-transform: uppercase ;' // shrink/uppercase labels
62
136
  + 'border-radius: 0 !important ;' // square borders
63
- + 'transition: transform 0.1s ease-in-out, box-shadow 0.1s ease-in-out ;' // smoothen hover fx
137
+ + 'transition: var(--btn-transition) ;' // smoothen hover fx
138
+ + '-webkit-transition: var(--btn-transition) ; -moz-transition: var(--btn-transition) ;'
139
+ + '-o-transition: var(--btn-transition) ; -ms-transition: var(--btn-transition) ;'
64
140
  + 'cursor: pointer !important ;' // add finger cursor
65
141
  + `border: 1px solid ${ this.imports.env.ui.scheme == 'dark' ? 'white' : 'black' } !important ;`
66
142
  + 'padding: 8px !important ; min-width: 102px }' // resize
@@ -71,78 +147,5 @@ window.modals = {
71
147
  `.${this.class} .modal-buttons { margin-left: -13px !important }` : '' )
72
148
  + `.about-em { color: ${ this.imports.env.ui.scheme == 'dark' ? 'white' : 'green' } !important }`
73
149
  )
74
- },
75
-
76
- observeRemoval(modal, modalType) { // to maintain stack for proper nav
77
- const modalBG = modal.parentNode
78
- new MutationObserver(([mutation], obs) => {
79
- mutation.removedNodes.forEach(removedNode => { if (removedNode == modalBG) {
80
- if (this.stack[0] == modalType) { // new modal not launched, implement nav back logic
81
- this.stack.shift() // remove this modal type from stack 1st
82
- const prevModalType = this.stack[0]
83
- if (prevModalType) { // open it
84
- this.stack.shift() // remove type from stack since re-added on open
85
- this.open(prevModalType)
86
- }
87
- }
88
- obs.disconnect()
89
- }})
90
- }).observe(modalBG.parentNode, { childList: true, subtree: true })
91
- },
92
-
93
- about() {
94
-
95
- // Show modal
96
- const aboutModal = this.alert(
97
- `${this.imports.app.symbol} ${chrome.runtime.getManifest().name}`, // title
98
- '🧠 Author: ' // msg
99
- + `<a href="${this.imports.app.author.url}">${this.imports.app.author.name}</a> `
100
- + `& <a href="${this.imports.app.urls.contributors}">contributors</a>\n`
101
- + `🏷️ Version: <span class="about-em">${this.imports.app.version}</span>\n`
102
- + '📜 Open source code: '
103
- + `<a href="${this.imports.app.urls.gitHub}" target="_blank" rel="nopener">`
104
- + this.imports.app.urls.gitHub + '</a>\n'
105
- + '⚡ Powered by: '
106
- + `<a href="${this.imports.app.urls.chatgptJS}" target="_blank" rel="noopener">chatgpt.js</a>`,
107
- [ function getSupport(){}, function rateUs(){}, function moreAiExtensions(){} ], // button labels
108
- '', 656 // modal width
109
- )
110
-
111
- // Format text
112
- aboutModal.querySelector('h2').style.cssText = (
113
- 'text-align: center ; font-size: 51px ; line-height: 46px ; padding: 15px 0' )
114
- aboutModal.querySelector('p').style.cssText = (
115
- 'text-align: center ; overflow-wrap: anywhere ;'
116
- + `margin: ${ this.imports.env.browser.isPortrait ? '6px 0 -16px' : '3px 0 0' }` )
117
-
118
- // Hack buttons
119
- aboutModal.querySelector('.modal-buttons').style.justifyContent = 'center'
120
- aboutModal.querySelectorAll('button').forEach(btn => {
121
- btn.style.cssText = 'height: 55px ; min-width: 136px ; text-align: center'
122
-
123
- // Replace buttons w/ clones that don't dismiss modal
124
- const btnClone = btn.cloneNode(true)
125
- btn.parentNode.replaceChild(btnClone, btn) ; btn = btnClone
126
- btn.onclick = () => this.safeWinOpen(
127
- btn.textContent == 'Get Support' ? `${modals.imports.app.urls.gitHub}/issues`
128
- : btn.textContent == 'Rate Us' ? `${modals.imports.app.urls.gitHub}/discussions`
129
- : modals.imports.app.urls.relatedExtensions
130
- )
131
-
132
- // Prepend emoji
133
- if (/support/i.test(btn.textContent))
134
- btn.textContent = '🧠 ' + btn.textContent
135
- else if (/rate/i.test(btn.textContent))
136
- btn.textContent = '⭐ ' + btn.textContent
137
- else if (/extensions/i.test(btn.textContent))
138
- btn.textContent = '🧠 ' + btn.textContent
139
-
140
- // Hide Dismiss button
141
- else btn.style.display = 'none'
142
- })
143
-
144
- return aboutModal
145
- },
146
-
147
- safeWinOpen(url) { open(url, '_blank', 'noopener') } // to prevent backdoor vulnerabilities
150
+ }
148
151
  };
@@ -1,5 +1,5 @@
1
1
  // NOTE: This script relies on the powerful chatgpt.js library @ https://chatgpt.js.org
2
- // © 2023–2024 KudoAI & contributors under the MIT license
2
+ // © 2023–2025 KudoAI & contributors under the MIT license
3
3
 
4
4
  (async () => {
5
5
 
@@ -15,8 +15,8 @@
15
15
  const { app } = await chrome.storage.sync.get('app')
16
16
 
17
17
  // Export DEPENDENCIES to imported resources
18
- dom.imports.import({ env }) // for env.ui.scheme
19
- modals.imports.import({ app, env }) // for app data + env.ui.scheme
18
+ dom.import({ env }) // for env.ui.scheme
19
+ modals.import({ app, env }) // for app data + env.<browser|ui> flags
20
20
 
21
21
  // Add CHROME MSG listener
22
22
  chrome.runtime.onMessage.addListener(req => { // from service-worker.js + popup/index.html
@@ -45,10 +45,18 @@
45
45
 
46
46
  // Append styled state word
47
47
  if (foundState) {
48
- const styledStateSpan = dom.create.elem('span')
49
- styledStateSpan.style.cssText = `color: ${
50
- foundState == 'OFF' ? '#ef4848 ; text-shadow: rgba(255, 169, 225, 0.44) 2px 1px 5px'
51
- : '#5cef48 ; text-shadow: rgba(255, 250, 169, 0.38) 2px 1px 5px' }`
48
+ const stateStyles = {
49
+ on: {
50
+ light: 'color: #5cef48 ; text-shadow: rgba(255,250,169,0.38) 2px 1px 5px',
51
+ dark: 'color: #5cef48 ; text-shadow: rgb(55, 255, 0) 3px 0 10px'
52
+ },
53
+ off: {
54
+ light: 'color: #ef4848 ; text-shadow: rgba(255,169,225,0.44) 2px 1px 5px',
55
+ dark: 'color: #ef4848 ; text-shadow: rgba(255, 116, 116, 0.87) 3px 0 9px'
56
+ }
57
+ }
58
+ const styledStateSpan = document.createElement('span')
59
+ styledStateSpan.style.cssText = stateStyles[foundState.toLowerCase()][env.ui.scheme]
52
60
  styledStateSpan.append(foundState) ; notif.append(styledStateSpan)
53
61
  }
54
62
  }
@@ -79,11 +87,10 @@
79
87
  await chatgpt.isLoaded()
80
88
  await new Promise(resolve => setTimeout(resolve, 500)); // sleep .5s
81
89
 
82
- // Add STARS styles for modals
83
- ['black', 'white'].forEach(color => document.head.append(
90
+ // Add RISING PARTICLES styles for modals
91
+ ['gray', 'white'].forEach(color => document.head.append(
84
92
  dom.create.elem('link', { rel: 'stylesheet',
85
- href: `https://assets.aiwebextensions.com/styles/rising-stars/dist/${
86
- color}.min.css?v=0cde30f9ae3ce99ae998141f6e7a36de9b0cc2e7`
93
+ href: `https://assets.aiwebextensions.com/styles/rising-particles/dist/${color}.min.css?v=727feff`
87
94
  })))
88
95
 
89
96
  if (config.extensionDisabled) return