@kudoai/chatgpt.js 3.3.5 → 3.4.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/README.md +28 -21
- package/chatgpt.js +129 -78
- package/dist/chatgpt.min.js +3 -3
- package/docs/README.md +28 -21
- package/docs/USERGUIDE.md +3 -3
- package/package.json +18 -11
- package/starters/chrome/docs/README.md +10 -8
- package/starters/chrome/extension/components/icons.js +32 -0
- package/starters/chrome/extension/components/modals.js +121 -0
- package/starters/chrome/extension/content.js +121 -47
- package/starters/chrome/extension/icons/faded/icon128.png +0 -0
- package/starters/chrome/extension/icons/faded/icon16.png +0 -0
- package/starters/chrome/extension/icons/faded/icon32.png +0 -0
- package/starters/chrome/extension/icons/faded/icon64.png +0 -0
- package/starters/chrome/extension/lib/chatgpt.js +129 -78
- package/starters/chrome/extension/lib/dom.js +28 -0
- package/starters/chrome/extension/lib/settings.js +30 -0
- package/starters/chrome/extension/manifest.json +25 -22
- package/starters/chrome/extension/popup/controller.js +138 -0
- package/starters/chrome/extension/popup/index.html +7 -44
- package/starters/chrome/extension/popup/style.css +15 -6
- package/starters/chrome/extension/service-worker.js +38 -0
- package/starters/greasemonkey/chatgpt.js-greasemonkey-starter.user.js +12 -12
- package/starters/greasemonkey/docs/README.md +2 -0
- package/starters/chrome/extension/background.js +0 -14
- package/starters/chrome/extension/lib/settings-utils.js +0 -24
- package/starters/chrome/extension/popup/popup.js +0 -92
- package/starters/chrome/media/images/icons/refresh/icon16.png +0 -0
- package/starters/chrome/media/images/icons/refresh/icon50.png +0 -0
- /package/starters/chrome/{media/images → images}/icons/question-mark/icon16.png +0 -0
- /package/starters/chrome/{media/images → images}/icons/question-mark/icon512.png +0 -0
- /package/starters/chrome/{media/images → images}/screenshots/chatgpt-extension-in-list.png +0 -0
- /package/starters/chrome/{media/images → images}/screenshots/developer-mode-toggle.png +0 -0
- /package/starters/chrome/{media/images → images}/screenshots/developer-mode-toggle.psd +0 -0
- /package/starters/chrome/{media/images → images}/screenshots/extension-loaded.png +0 -0
- /package/starters/chrome/{media/images → images}/screenshots/load-unpacked-button.png +0 -0
- /package/starters/chrome/{media/images → images}/screenshots/reload-extension-button.png +0 -0
- /package/starters/chrome/{media/images → images}/screenshots/reload-page-button.png +0 -0
- /package/starters/chrome/{media/images → images}/screenshots/select-extension-folder.png +0 -0
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<a href="https://github.com/KudoAI/chatgpt.js/tree/main/docs/ja#readme">日本</a> |
|
|
17
17
|
<a href="https://github.com/KudoAI/chatgpt.js/tree/main/docs/ko#readme">한국인</a> |
|
|
18
18
|
<a href="https://github.com/KudoAI/chatgpt.js/tree/main/docs/hi#readme">हिंदी</a> |
|
|
19
|
-
<a href="https://github.com/KudoAI/chatgpt.js/tree/main/docs/
|
|
19
|
+
<a href="https://github.com/KudoAI/chatgpt.js/tree/main/docs/ne#readme">नेपाली</a> |
|
|
20
20
|
<a href="https://github.com/KudoAI/chatgpt.js/tree/main/docs/de#readme">Deutsch</a> |
|
|
21
21
|
<a href="https://github.com/KudoAI/chatgpt.js/tree/main/docs/es#readme">Español</a> |
|
|
22
22
|
<a href="https://github.com/KudoAI/chatgpt.js/tree/main/docs/fr#readme">Français</a> |
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
|
|
48
48
|
[](https://github.com/KudoAI/chatgpt.js/stargazers)
|
|
49
49
|
[](https://github.com/KudoAI/chatgpt.js/blob/main/LICENSE.md)
|
|
50
|
-
[](https://github.com/KudoAI/chatgpt.js/tree/v3.4.0/dist/chatgpt.min.js)
|
|
51
51
|
[](https://www.codefactor.io/repository/github/kudoai/chatgpt.js)
|
|
52
52
|
[](https://sonarcloud.io/component_measures?metric=new_vulnerabilities&id=kudoai_chatgpt.js)
|
|
53
53
|
[](https://github.com/sindresorhus/awesome-chatgpt#javascript)
|
|
@@ -79,13 +79,14 @@
|
|
|
79
79
|
|
|
80
80
|
</div>
|
|
81
81
|
|
|
82
|
-
>
|
|
82
|
+
> [!NOTE]
|
|
83
|
+
> To always import the latest version (not recommended in production!) replace the versioned jsDelivr URL with: `https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js/chatgpt.min.js`
|
|
83
84
|
|
|
84
85
|
### ES11 (2020):
|
|
85
86
|
|
|
86
87
|
```js
|
|
87
88
|
(async () => {
|
|
88
|
-
await import('https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.
|
|
89
|
+
await import('https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.4.0/dist/chatgpt.min.js');
|
|
89
90
|
// Your code here...
|
|
90
91
|
})();
|
|
91
92
|
```
|
|
@@ -94,7 +95,7 @@
|
|
|
94
95
|
|
|
95
96
|
```js
|
|
96
97
|
var xhr = new XMLHttpRequest();
|
|
97
|
-
xhr.open('GET', 'https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.
|
|
98
|
+
xhr.open('GET', 'https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.4.0/dist/chatgpt.min.js');
|
|
98
99
|
xhr.onload = function () {
|
|
99
100
|
if (xhr.status === 200) {
|
|
100
101
|
var chatgptJS = document.createElement('script');
|
|
@@ -112,11 +113,12 @@ function yourCode() {
|
|
|
112
113
|
|
|
113
114
|
### <img style="margin: 0 2px -0.065rem 0" height=17 src="https://media.chatgptjs.org/images/icons/platforms/tampermonkey/icon28.png?a3e53bf7"><img style="margin: 0 2px -0.035rem 1px" height=17.5 src="https://media.chatgptjs.org/images/icons/platforms/violentmonkey/icon25.png?a3e53bf7"> Greasemonkey:
|
|
114
115
|
|
|
115
|
-
>
|
|
116
|
+
> [!NOTE]
|
|
117
|
+
> To use a starter template: [kudoai/chatgpt.js-greasemonkey-starter](https://github.com/KudoAI/chatgpt.js-greasemonkey-starter)
|
|
116
118
|
|
|
117
119
|
```js
|
|
118
120
|
...
|
|
119
|
-
// @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.
|
|
121
|
+
// @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.4.0/dist/chatgpt.min.js
|
|
120
122
|
// ==/UserScript==
|
|
121
123
|
|
|
122
124
|
// Your code here...
|
|
@@ -124,7 +126,8 @@ function yourCode() {
|
|
|
124
126
|
|
|
125
127
|
### <img style="margin: 0 2px -1px 0" height=16 src="https://media.chatgptjs.org/images/icons/platforms/chrome/icon16.png?8c852fa5"> Chrome:
|
|
126
128
|
|
|
127
|
-
>
|
|
129
|
+
> [!NOTE]
|
|
130
|
+
> To use a starter template: [kudoai/chatgpt.js-chrome-starter](https://github.com/KudoAI/chatgpt.js-chrome-starter)
|
|
128
131
|
|
|
129
132
|
Since Google does not allow remote code, importing chatgpt.js locally is required:
|
|
130
133
|
|
|
@@ -185,7 +188,7 @@ chatgpt.get('reply', 'last');
|
|
|
185
188
|
|
|
186
189
|
Each call equally fetches the last response. If you think it works, it probably will... so just type it!
|
|
187
190
|
|
|
188
|
-
If it didn't, check out the extended [userguide](https://github.com/KudoAI/chatgpt.js/blob/v3.
|
|
191
|
+
If it didn't, check out the extended [userguide](https://github.com/KudoAI/chatgpt.js/blob/v3.4.0/docs/USERGUIDE.md), or simply submit an [issue](https://github.com/KudoAI/chatgpt.js/issues) or [PR](https://github.com/KudoAI/chatgpt.js/pulls) and it will be integrated, ezpz!
|
|
189
192
|
|
|
190
193
|
<img height=8px width="100%" src="https://media.chatgptjs.org/images/separators/gradient-aqua.png?78210a7">
|
|
191
194
|
|
|
@@ -327,6 +330,12 @@ This library exists thanks to code, translations, issues & ideas from the follow
|
|
|
327
330
|
[](https://github.com/FarukhS52)
|
|
328
331
|
[](https://github.com/Innovatorcloudy)
|
|
329
332
|
[](https://github.com/barbarian360)
|
|
333
|
+
[](https://github.com/adityadeshpande09)
|
|
334
|
+
[](https://github.com/twlite)
|
|
335
|
+
[](https://github.com/sulav7)
|
|
336
|
+
[](https://github.com/samir-byte)
|
|
337
|
+
[](https://github.com/ghimirebibek)
|
|
338
|
+
[](https://github.com/JanumalaAkhilendra)
|
|
330
339
|
[](https://github.com/dependabot)
|
|
331
340
|
<a href="https://chatgpt.com"><picture><source type="image/png" media="(prefers-color-scheme: dark)" srcset="https://images.weserv.nl/?url=https://cdn.jsdelivr.net/gh/KudoAI/chatgpt.js@main/media/images/icons/platforms/chatgpt/black-on-white/icon189.png?h=46&w=46&mask=circle&maxage=7d"><img src="https://images.weserv.nl/?url=https://cdn.jsdelivr.net/gh/KudoAI/chatgpt.js@main/media/images/icons/platforms/chatgpt/white-on-black/icon189.png?h=46&w=46&mask=circle&maxage=7d" title="ChatGPT"></picture></a>
|
|
332
341
|
<a href="https://poe.com"><picture><source type="image/png" media="(prefers-color-scheme: dark)" srcset="https://images.weserv.nl/?url=https://cdn.jsdelivr.net/gh/KudoAI/chatgpt.js@main/media/images/icons/platforms/poe/w-purple-blue-stripes/black-on-white/icon175.png?h=46&w=46&mask=circle&maxage=7d"><img src="https://images.weserv.nl/?url=https://cdn.jsdelivr.net/gh/KudoAI/chatgpt.js@main/media/images/icons/platforms/poe/w-purple-blue-stripes/white-on-black/icon175.png?h=46&w=46&mask=circle&maxage=7d" title="Poe"></picture></a>
|
|
@@ -336,20 +345,18 @@ This library exists thanks to code, translations, issues & ideas from the follow
|
|
|
336
345
|
|
|
337
346
|
<img height=8px width="100%" src="https://media.chatgptjs.org/images/separators/gradient-aqua.png?78210a7">
|
|
338
347
|
|
|
339
|
-
<div
|
|
340
|
-
|
|
341
|
-
## 🤝 Partners
|
|
342
|
-
|
|
343
|
-
</div>
|
|
348
|
+
<div align="center">
|
|
344
349
|
|
|
345
|
-
|
|
350
|
+
<br>
|
|
346
351
|
|
|
347
|
-
|
|
352
|
+
**chatgpt.js** is funded in part by:
|
|
348
353
|
|
|
349
|
-
<
|
|
350
|
-
<
|
|
351
|
-
|
|
352
|
-
|
|
354
|
+
<a href="https://microsoft.com">
|
|
355
|
+
<picture>
|
|
356
|
+
<source type="image/png" media="(prefers-color-scheme: dark)" srcset="https://media.chatgptjs.org/images/logos/partners/microsoft/white.png?963f917">
|
|
357
|
+
<img width=300 src="https://media.chatgptjs.org/images/logos/partners/microsoft/colored.png?963f917">
|
|
358
|
+
</picture>
|
|
359
|
+
</a>
|
|
353
360
|
|
|
354
361
|
</div>
|
|
355
362
|
|
|
@@ -360,7 +367,7 @@ This library exists thanks to code, translations, issues & ideas from the follow
|
|
|
360
367
|
<div align="center">
|
|
361
368
|
|
|
362
369
|
**[Releases](https://github.com/KudoAI/chatgpt.js/releases)** /
|
|
363
|
-
[Userguide](https://github.com/KudoAI/chatgpt.js/blob/v3.
|
|
370
|
+
[Userguide](https://github.com/KudoAI/chatgpt.js/blob/v3.4.0/docs/USERGUIDE.md) /
|
|
364
371
|
[Discuss](https://github.com/KudoAI/chatgpt.js/discussions) /
|
|
365
372
|
[Back to top ↑](#top)
|
|
366
373
|
|
package/chatgpt.js
CHANGED
|
@@ -8,7 +8,7 @@ localStorage.alertQueue = JSON.stringify([]);
|
|
|
8
8
|
localStorage.notifyProps = JSON.stringify({ queue: { topRight: [], bottomRight: [], bottomLeft: [], topLeft: [] }});
|
|
9
9
|
|
|
10
10
|
// Define chatgpt API
|
|
11
|
-
const chatgpt = {
|
|
11
|
+
const chatgpt = {
|
|
12
12
|
openAIaccessToken: {}, endpoints: {
|
|
13
13
|
assets: 'https://cdn.jsdelivr.net/gh/KudoAI/chatgpt.js',
|
|
14
14
|
openAI: {
|
|
@@ -64,9 +64,63 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
64
64
|
// [ title/msg = strings, btns = [named functions], checkbox = named function, width (px) = int ] = optional
|
|
65
65
|
// * Spaces are inserted into button labels by parsing function names in camel/kebab/snake case
|
|
66
66
|
|
|
67
|
+
// Init env context
|
|
67
68
|
const scheme = chatgpt.isDarkMode() ? 'dark' : 'light',
|
|
68
69
|
isMobile = chatgpt.browser.isMobile();
|
|
69
70
|
|
|
71
|
+
// Define event handlers
|
|
72
|
+
const handlers = {
|
|
73
|
+
|
|
74
|
+
dismiss: {
|
|
75
|
+
click(event) {
|
|
76
|
+
if (event.target == event.currentTarget || event.target.closest('[class*="-close-btn]'))
|
|
77
|
+
dismissAlert()
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
key(event) {
|
|
81
|
+
if (!/^(?: |Space|Enter|Return|Esc)/.test(event.key) || ![32, 13, 27].includes(event.keyCode))
|
|
82
|
+
return
|
|
83
|
+
for (const alertId of alertQueue) { // look to handle only if triggering alert is active
|
|
84
|
+
const alert = document.getElementById(alertId)
|
|
85
|
+
if (!alert || alert.style.display == 'none') return
|
|
86
|
+
if (event.key.startsWith('Esc') || event.keyCode == 27) dismissAlert() // and do nothing
|
|
87
|
+
else { // Space/Enter pressed
|
|
88
|
+
const mainButton = alert.querySelector('.modal-buttons').lastChild // look for main button
|
|
89
|
+
if (mainButton) { mainButton.click() ; event.preventDefault() } // click if found
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
drag: {
|
|
96
|
+
mousedown(event) { // find modal, attach listeners, init XY offsets
|
|
97
|
+
if (event.button != 0) return // prevent non-left-click drag
|
|
98
|
+
if (getComputedStyle(event.target).cursor == 'pointer') return // prevent drag on interactive elems
|
|
99
|
+
chatgpt.draggableElem = event.currentTarget
|
|
100
|
+
chatgpt.draggableElem.style.cursor = 'grabbing'
|
|
101
|
+
event.preventDefault(); // prevent sub-elems like icons being draggable
|
|
102
|
+
['mousemove', 'mouseup'].forEach(event => document.addEventListener(event, handlers.drag[event]))
|
|
103
|
+
const draggableElemRect = chatgpt.draggableElem.getBoundingClientRect()
|
|
104
|
+
handlers.drag.offsetX = event.clientX - draggableElemRect.left +21
|
|
105
|
+
handlers.drag.offsetY = event.clientY - draggableElemRect.top +12
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
mousemove(event) { // drag modal
|
|
109
|
+
if (!chatgpt.draggableElem) return
|
|
110
|
+
const newX = event.clientX - handlers.drag.offsetX,
|
|
111
|
+
newY = event.clientY - handlers.drag.offsetY
|
|
112
|
+
Object.assign(chatgpt.draggableElem.style, { left: `${newX}px`, top: `${newY}px` })
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
mouseup() { // remove listeners, reset chatgpt.draggableElem
|
|
116
|
+
chatgpt.draggableElem.style.cursor = 'inherit';
|
|
117
|
+
['mousemove', 'mouseup'].forEach(event =>
|
|
118
|
+
document.removeEventListener(event, handlers.drag[event]))
|
|
119
|
+
chatgpt.draggableElem = null
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
70
124
|
// Create modal parent/children elements
|
|
71
125
|
const modalContainer = document.createElement('div');
|
|
72
126
|
modalContainer.id = Math.floor(chatgpt.randomFloat() * 1000000) + Date.now();
|
|
@@ -76,7 +130,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
76
130
|
modalMessage = document.createElement('p');
|
|
77
131
|
|
|
78
132
|
// Create/append/update modal style (if missing or outdated)
|
|
79
|
-
const thisUpdated =
|
|
133
|
+
const thisUpdated = 1734685032942; // timestamp of last edit for this file's `modalStyle`
|
|
80
134
|
let modalStyle = document.querySelector('#chatgpt-modal-style'); // try to select existing style
|
|
81
135
|
if (!modalStyle || parseInt(modalStyle.getAttribute('last-updated'), 10) < thisUpdated) { // if missing or outdated
|
|
82
136
|
if (!modalStyle) { // outright missing, create/id/attr/append it first
|
|
@@ -88,26 +142,31 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
88
142
|
'.no-mobile-tap-outline { outline: none ; -webkit-tap-highlight-color: transparent }'
|
|
89
143
|
|
|
90
144
|
// Background styles
|
|
91
|
-
+ '.chatgpt-modal {'
|
|
145
|
+
+ '.chatgpt-modal {'
|
|
146
|
+
+ 'pointer-events: auto ;' // override any disabling from site modals (like guest login spam)
|
|
92
147
|
+ 'position: fixed ; top: 0 ; left: 0 ; width: 100% ; height: 100% ;' // expand to full view-port
|
|
93
|
-
+ 'background-color
|
|
94
|
-
+ 'transition: background-color 0.05s ease ;' // speed to transition in show alert routine
|
|
148
|
+
+ 'transition: background-color 0.25s ease !important ;' // speed to show bg dim
|
|
95
149
|
+ 'display: flex ; justify-content: center ; align-items: center ; z-index: 9999 }' // align
|
|
96
150
|
|
|
97
151
|
// Alert styles
|
|
98
152
|
+ '.chatgpt-modal > div {'
|
|
99
|
-
+ '
|
|
100
|
-
+ '
|
|
101
|
-
+ `
|
|
102
|
-
+
|
|
153
|
+
+ 'position: absolute ;' // to be click-draggable
|
|
154
|
+
+ 'opacity: 0 ;' // to fade-in
|
|
155
|
+
+ `border: 1px solid ${ scheme == 'dark' ? 'white' : '#b5b5b5' };`
|
|
156
|
+
+ `color: ${ scheme == 'dark' ? 'white' : 'black' };`
|
|
157
|
+
+ `background-color: ${ scheme == 'dark' ? 'black' : 'white' };`
|
|
158
|
+
+ 'transform: translateX(-3px) translateY(7px) ;' // offset to move-in from
|
|
159
|
+
+ 'transition: opacity 0.65s cubic-bezier(.165,.84,.44,1),' // for fade-ins
|
|
160
|
+
+ 'transform 0.55s cubic-bezier(.165,.84,.44,1) ;' // for move-ins
|
|
161
|
+
+ 'max-width: 75vw ; word-wrap: break-word ;'
|
|
103
162
|
+ 'padding: 20px ; margin: 12px 23px ; border-radius: 15px ; box-shadow: 0 30px 60px rgba(0, 0, 0, .12) ;'
|
|
104
163
|
+ ' -webkit-user-select: none ; -moz-user-select: none ; -ms-user-select: none ; user-select: none ; }'
|
|
105
164
|
+ '.chatgpt-modal h2 { margin-bottom: 9px }'
|
|
106
165
|
+ `.chatgpt-modal a { color: ${ scheme == 'dark' ? '#00cfff' : '#1e9ebb' }}`
|
|
107
|
-
+ '.chatgpt-modal.animated > div { opacity:
|
|
108
|
-
+ '@keyframes alert-zoom-fade-out {
|
|
109
|
-
|
|
110
|
-
|
|
166
|
+
+ '.chatgpt-modal.animated > div { z-index: 13456 ; opacity: 0.98 ; transform: translateX(0) translateY(0) }'
|
|
167
|
+
+ '@keyframes alert-zoom-fade-out {'
|
|
168
|
+
+ '0% { opacity: 1 } 50% { opacity: 0.25 ; transform: scale(1.05) }'
|
|
169
|
+
+ '100% { opacity: 0 ; transform: scale(1.35) }}'
|
|
111
170
|
|
|
112
171
|
// Button styles
|
|
113
172
|
+ '.modal-buttons { display: flex ; justify-content: flex-end ; margin: 20px -5px -3px 0 ;'
|
|
@@ -140,7 +199,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
140
199
|
+ `border: 1px solid ${ scheme == 'dark' ? 'white' : 'black' } ;`
|
|
141
200
|
+ 'background-color: black ; position: inherit }'
|
|
142
201
|
+ '.chatgpt-modal input[type="checkbox"]:focus { outline: none ; box-shadow: none }'
|
|
143
|
-
);
|
|
202
|
+
);
|
|
144
203
|
}
|
|
145
204
|
|
|
146
205
|
// Insert text into elements
|
|
@@ -210,7 +269,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
210
269
|
const modalElems = [closeBtn, modalTitle, modalMessage, modalButtons, checkboxDiv];
|
|
211
270
|
modalElems.forEach((elem) => { modal.append(elem); });
|
|
212
271
|
modal.style.width = `${ width || 458 }px`;
|
|
213
|
-
modalContainer.append(modal); document.body.append(modalContainer);
|
|
272
|
+
modalContainer.append(modal); document.body.append(modalContainer);
|
|
214
273
|
|
|
215
274
|
// Enqueue alert
|
|
216
275
|
let alertQueue = JSON.parse(localStorage.alertQueue);
|
|
@@ -221,39 +280,22 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
221
280
|
modalContainer.style.display = 'none';
|
|
222
281
|
if (alertQueue.length === 1) {
|
|
223
282
|
modalContainer.style.display = '';
|
|
224
|
-
setTimeout(() => { //
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
283
|
+
setTimeout(() => { // dim bg
|
|
284
|
+
modal.parentNode.style.backgroundColor = `rgba(67, 70, 72, ${ scheme == 'dark' ? 0.62 : 0.33 })`
|
|
285
|
+
modal.parentNode.classList.add('animated')
|
|
286
|
+
}, 100) // delay for transition fx
|
|
228
287
|
}
|
|
229
288
|
|
|
230
|
-
//
|
|
231
|
-
const clickHandler = event => { // explicitly defined to support removal post-dismissal
|
|
232
|
-
if (event.target == event.currentTarget || event.target instanceof SVGPathElement) dismissAlert(); };
|
|
233
|
-
const keyHandler = event => { // to dismiss active alert
|
|
234
|
-
const dismissKeys = [' ', 'Spacebar', 'Enter', 'Return', 'Escape', 'Esc'],
|
|
235
|
-
dismissKeyCodes = [32, 13, 27];
|
|
236
|
-
if (dismissKeys.includes(event.key) || dismissKeyCodes.includes(event.keyCode)) {
|
|
237
|
-
for (const alertId of alertQueue) { // look to handle only if triggering alert is active
|
|
238
|
-
const alert = document.getElementById(alertId);
|
|
239
|
-
if (alert && alert.style.display !== 'none') { // active alert found
|
|
240
|
-
if (event.key.includes('Esc') || event.keyCode == 27) // esc pressed
|
|
241
|
-
dismissAlert(); // dismiss alert & do nothing
|
|
242
|
-
else if ([' ', 'Spacebar', 'Enter', 'Return'].includes(event.key) || [32, 13].includes(event.keyCode)) { // space/enter pressed
|
|
243
|
-
const mainButton = alert.querySelector('.modal-buttons').lastChild; // look for main button
|
|
244
|
-
if (mainButton) { mainButton.click(); event.preventDefault(); } // click if found
|
|
245
|
-
} return;
|
|
246
|
-
}}}};
|
|
247
|
-
|
|
248
|
-
// Add listeners to dismiss alert
|
|
289
|
+
// Add listeners
|
|
249
290
|
const dismissElems = [modalContainer, closeBtn, closeSVG, dismissBtn];
|
|
250
|
-
dismissElems.forEach(elem => elem.onclick =
|
|
251
|
-
document.addEventListener('keydown',
|
|
291
|
+
dismissElems.forEach(elem => elem.onclick = handlers.dismiss.click);
|
|
292
|
+
document.addEventListener('keydown', handlers.dismiss.key);
|
|
293
|
+
modal.onmousedown = handlers.drag.mousedown // enable click-dragging
|
|
252
294
|
|
|
253
295
|
// Define alert dismisser
|
|
254
296
|
const dismissAlert = () => {
|
|
255
297
|
modalContainer.style.backgroundColor = 'transparent';
|
|
256
|
-
modal.style.animation = 'alert-zoom-fade-out 0.
|
|
298
|
+
modal.style.animation = 'alert-zoom-fade-out 0.135s ease-out';
|
|
257
299
|
setTimeout(() => { // delay removal for fade-out
|
|
258
300
|
|
|
259
301
|
// Remove alert
|
|
@@ -261,7 +303,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
261
303
|
alertQueue = JSON.parse(localStorage.alertQueue);
|
|
262
304
|
alertQueue.shift(); // + memory
|
|
263
305
|
localStorage.alertQueue = JSON.stringify(alertQueue); // + storage
|
|
264
|
-
document.removeEventListener('keydown',
|
|
306
|
+
document.removeEventListener('keydown', handlers.dismiss.key); // prevent memory leaks
|
|
265
307
|
|
|
266
308
|
// Check for pending alerts in queue
|
|
267
309
|
if (alertQueue.length > 0) {
|
|
@@ -272,7 +314,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
272
314
|
}, 500);
|
|
273
315
|
}
|
|
274
316
|
|
|
275
|
-
},
|
|
317
|
+
}, 135);
|
|
276
318
|
};
|
|
277
319
|
|
|
278
320
|
return modalContainer.id; // if assignment used
|
|
@@ -557,7 +599,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
557
599
|
.replace('Copy code', '');
|
|
558
600
|
msgs.push(sender + ': ' + msg);
|
|
559
601
|
});
|
|
560
|
-
transcript = msgs.join('\n\n');
|
|
602
|
+
transcript = msgs.join('\n\n');
|
|
561
603
|
|
|
562
604
|
// ...or from getChatData(chatToGet)
|
|
563
605
|
} else {
|
|
@@ -606,7 +648,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
606
648
|
} else { // auto-save to file
|
|
607
649
|
|
|
608
650
|
if (format == 'md') { // remove extraneous HTML + fix file extension
|
|
609
|
-
const mdMatch =
|
|
651
|
+
const mdMatch = /<.*<h1(.|\n)*?href=".*?continue[^"]*".*?\/a>.*?<[^/]/.exec(transcript)[1];
|
|
610
652
|
transcript = mdMatch || transcript; filename = filename.replace('.html', '.md');
|
|
611
653
|
}
|
|
612
654
|
const blob = new Blob([transcript],
|
|
@@ -621,20 +663,20 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
621
663
|
focusChatbar() { chatgpt.getChatBox()?.focus(); },
|
|
622
664
|
|
|
623
665
|
footer: {
|
|
624
|
-
get() { return document.querySelector('
|
|
666
|
+
get() { return document.querySelector('.min-h-4'); },
|
|
625
667
|
|
|
626
|
-
hide() {
|
|
668
|
+
hide() {
|
|
627
669
|
const footer = chatgpt.footer.get();
|
|
628
670
|
if (!footer) return console.error('Footer element not found!');
|
|
629
671
|
if (footer.style.visibility == 'hidden') return console.info('Footer already hidden!');
|
|
630
|
-
footer.style.
|
|
672
|
+
footer.style.display = 'none';
|
|
631
673
|
},
|
|
632
674
|
|
|
633
675
|
show() {
|
|
634
676
|
const footer = chatgpt.footer.get();
|
|
635
677
|
if (!footer) return console.error('Footer element not found!');
|
|
636
678
|
if (footer.style.visibility != 'hidden') return console.info('Footer already shown!');
|
|
637
|
-
footer.style.
|
|
679
|
+
footer.style.display = 'inherit'
|
|
638
680
|
}
|
|
639
681
|
},
|
|
640
682
|
|
|
@@ -888,12 +930,15 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
888
930
|
getHeaderDiv() { return chatgpt.header.get(); },
|
|
889
931
|
getLastPrompt() { return chatgpt.getChatData('active', 'msg', 'user', 'latest'); },
|
|
890
932
|
getLastResponse() { return chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest'); },
|
|
891
|
-
|
|
933
|
+
|
|
934
|
+
getNewChatButton() {
|
|
935
|
+
return document.querySelector('button[data-testid*="new-chat-button"], button:has([d^="M15.6729"])'); },
|
|
936
|
+
|
|
892
937
|
getNewChatLink() { return document.querySelector('nav a[href="/"]'); },
|
|
893
938
|
getRegenerateButton() { return document.querySelector('button:has([d^="M3.06957"])'); },
|
|
894
939
|
|
|
895
940
|
getResponse() {
|
|
896
|
-
// * Returns response via DOM by index arg if OpenAI chat page is active, otherwise uses API w/ following args:
|
|
941
|
+
// * Returns response via DOM by index arg if OpenAI chat page is active, otherwise uses API w/ following args:
|
|
897
942
|
// chatToGet = index|title|id of chat to get (defaults to latest if '' unpassed)
|
|
898
943
|
// responseToGet = index of response to get (defaults to latest if '' unpassed)
|
|
899
944
|
// regenResponseToGet = index of regenerated response to get (defaults to latest if '' unpassed)
|
|
@@ -1147,7 +1192,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1147
1192
|
}
|
|
1148
1193
|
|
|
1149
1194
|
else if (element == 'dropdown') {
|
|
1150
|
-
if (!attrs?.items || // there no are options to add
|
|
1195
|
+
if (!attrs?.items || // there no are options to add
|
|
1151
1196
|
!Array.isArray(attrs.items) || // it's not an array
|
|
1152
1197
|
!attrs.items.length) // the array is empty
|
|
1153
1198
|
attrs.items = [{ text: '🤖 chatgpt.js option', value: 'chatgpt.js option value' }]; // set default dropdown entry
|
|
@@ -1168,7 +1213,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1168
1213
|
const addElementsToMenu = () => {
|
|
1169
1214
|
const optionButtons = document.querySelectorAll('a[role="menuitem"]');
|
|
1170
1215
|
let cssClasses;
|
|
1171
|
-
|
|
1216
|
+
|
|
1172
1217
|
for (const navLink of optionButtons)
|
|
1173
1218
|
if (navLink.textContent == 'Settings') {
|
|
1174
1219
|
cssClasses = navLink.classList;
|
|
@@ -1240,7 +1285,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1240
1285
|
+ (notificationDiv.isRight ? 'Right' : 'Left');
|
|
1241
1286
|
|
|
1242
1287
|
// Create/append/update notification style (if missing or outdated)
|
|
1243
|
-
const thisUpdated = 20231110; // datestamp of last edit for this file's `notifStyle`
|
|
1288
|
+
const thisUpdated = 20231110; // datestamp of last edit for this file's `notifStyle`
|
|
1244
1289
|
let notifStyle = document.querySelector('#chatgpt-notif-style'); // try to select existing style
|
|
1245
1290
|
if (!notifStyle || parseInt(notifStyle.getAttribute('last-updated'), 10) < thisUpdated) { // if missing or outdated
|
|
1246
1291
|
if (!notifStyle) { // outright missing, create/id/attr/append it first
|
|
@@ -1255,7 +1300,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1255
1300
|
+ 'opacity: 0 ; position: fixed ; z-index: 9999 ; font-size: 1.8rem ; color: white ;' // visibility
|
|
1256
1301
|
+ '-webkit-user-select: none ; -moz-user-select: none ; -ms-user-select: none ; user-select: none ;'
|
|
1257
1302
|
+ `transform: translateX(${ !notificationDiv.isRight ? '-' : '' }35px) ;` // init off-screen for transition fx
|
|
1258
|
-
+ ( shadow ? ( 'box-shadow: -8px 13px 25px 0 ' + ( /\b(shadow|on)\b/
|
|
1303
|
+
+ ( shadow ? ( 'box-shadow: -8px 13px 25px 0 ' + ( /\b(?:shadow|on)\b/i.test(shadow) ? 'gray' : shadow )) : '' ) + '}'
|
|
1259
1304
|
+ '.notif-close-btn { cursor: pointer ; float: right ; position: relative ; right: -4px ; margin-left: -3px ;'
|
|
1260
1305
|
+ 'display: grid }' // top-align for non-OpenAI sites
|
|
1261
1306
|
+ '@keyframes notif-zoom-fade-out { 0% { opacity: 1 ; transform: scale(1) }' // transition out keyframes
|
|
@@ -1263,7 +1308,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1263
1308
|
+ '45% { opacity: 0.05 ; transform: rotateX(-81deg) }'
|
|
1264
1309
|
+ '100% { opacity: 0 ; transform: rotateX(-180deg) scale(1.15) }}'
|
|
1265
1310
|
);
|
|
1266
|
-
}
|
|
1311
|
+
}
|
|
1267
1312
|
|
|
1268
1313
|
// Enqueue notification
|
|
1269
1314
|
let notifyProps = JSON.parse(localStorage.notifyProps);
|
|
@@ -1296,7 +1341,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1296
1341
|
notificationDiv.style.transition = 'transform 0.15s ease, opacity 0.15s ease';
|
|
1297
1342
|
}, 10);
|
|
1298
1343
|
|
|
1299
|
-
// Init delay before hiding
|
|
1344
|
+
// Init delay before hiding
|
|
1300
1345
|
const hideDelay = fadeDuration > notifDuration ? 0 // don't delay if fade exceeds notification duration
|
|
1301
1346
|
: notifDuration - fadeDuration; // otherwise delay for difference
|
|
1302
1347
|
|
|
@@ -1305,7 +1350,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1305
1350
|
notificationDiv.style.animation = `notif-zoom-fade-out ${ fadeDuration }s ease-out`;
|
|
1306
1351
|
clearTimeout(dismissFuncTID);
|
|
1307
1352
|
};
|
|
1308
|
-
const dismissFuncTID = setTimeout(dismissNotif, hideDelay * 1000); // maintain visibility for `hideDelay` secs, then dismiss
|
|
1353
|
+
const dismissFuncTID = setTimeout(dismissNotif, hideDelay * 1000); // maintain visibility for `hideDelay` secs, then dismiss
|
|
1309
1354
|
closeSVG.onclick = dismissNotif; // add to close button clicks
|
|
1310
1355
|
|
|
1311
1356
|
// Destroy notification
|
|
@@ -1341,8 +1386,9 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1341
1386
|
const functionNames = [];
|
|
1342
1387
|
for (const prop in this) {
|
|
1343
1388
|
if (typeof this[prop] == 'function') {
|
|
1344
|
-
const chatgptIsParent = !Object.keys(this)
|
|
1345
|
-
|
|
1389
|
+
const chatgptIsParent = !Object.keys(this)
|
|
1390
|
+
.find(obj => Object.keys(this[obj]).includes(this[prop].name))
|
|
1391
|
+
const functionParent = chatgptIsParent ? 'chatgpt' : 'other';
|
|
1346
1392
|
functionNames.push([functionParent, prop]);
|
|
1347
1393
|
} else if (typeof this[prop] == 'object') {
|
|
1348
1394
|
for (const nestedProp in this[prop]) {
|
|
@@ -1398,7 +1444,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1398
1444
|
|
|
1399
1445
|
renderHTML(node) {
|
|
1400
1446
|
const reTags = /<([a-z\d]+)\b([^>]*)>([\s\S]*?)<\/\1>/g,
|
|
1401
|
-
reAttributes = /(\S+)=['"]?((?:.(?!['"]?\s+\S+=|[>']))+.)['"]?/g,
|
|
1447
|
+
reAttributes = /(\S+)=['"]?((?:.(?!['"]?\s+\S+=|[>']))+.)['"]?/g, // eslint-disable-line
|
|
1402
1448
|
nodeContent = node.childNodes;
|
|
1403
1449
|
|
|
1404
1450
|
// Preserve consecutive spaces + line breaks
|
|
@@ -1453,7 +1499,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1453
1499
|
continue() { try { chatgpt.getContinueBtn().click(); } catch (err) { console.error(err.message); }},
|
|
1454
1500
|
|
|
1455
1501
|
get() {
|
|
1456
|
-
// * Returns response via DOM by index arg if OpenAI chat page is active, otherwise uses API w/ following args:
|
|
1502
|
+
// * Returns response via DOM by index arg if OpenAI chat page is active, otherwise uses API w/ following args:
|
|
1457
1503
|
// chatToGet = index|title|id of chat to get (defaults to latest if '' unpassed)
|
|
1458
1504
|
// responseToGet = index of response to get (defaults to latest if '' unpassed)
|
|
1459
1505
|
// regenResponseToGet = index of regenerated response to get (defaults to latest if '' unpassed)
|
|
@@ -1497,8 +1543,8 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1497
1543
|
: /^(?:10|ten)(?:th)?$/.test(strPos) ? 10 : 1 )
|
|
1498
1544
|
|
|
1499
1545
|
// Transform base number if suffixed
|
|
1500
|
-
* ( /(ty|ieth)$/.test(strPos) ? 10 : 1 ) // x 10 if -ty/ieth
|
|
1501
|
-
+ ( /teen(th)?$/.test(strPos) ? 10 : 0 ) // + 10 if -teen/teenth
|
|
1546
|
+
* ( /(?:ty|ieth)$/.test(strPos) ? 10 : 1 ) // x 10 if -ty/ieth
|
|
1547
|
+
+ ( /teen(?:th)?$/.test(strPos) ? 10 : 0 ) // + 10 if -teen/teenth
|
|
1502
1548
|
|
|
1503
1549
|
);
|
|
1504
1550
|
response = responseDivs[nthOfResponse - 1].textContent;
|
|
@@ -1682,14 +1728,14 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1682
1728
|
break;
|
|
1683
1729
|
}
|
|
1684
1730
|
}
|
|
1685
|
-
|
|
1731
|
+
|
|
1686
1732
|
// Apply CSS to make the added elements look like they belong to the website
|
|
1687
1733
|
this.elements.forEach(element => {
|
|
1688
1734
|
element.setAttribute('class', cssClasses);
|
|
1689
1735
|
element.style.maxHeight = element.style.minHeight = '44px'; // Fix the height of the element
|
|
1690
1736
|
element.style.margin = '2px 0';
|
|
1691
1737
|
});
|
|
1692
|
-
|
|
1738
|
+
|
|
1693
1739
|
// Create MutationObserver instance
|
|
1694
1740
|
const navBar = document.querySelector('nav');
|
|
1695
1741
|
if (!navBar) return console.error('Sidebar element not found!');
|
|
@@ -1746,7 +1792,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1746
1792
|
}
|
|
1747
1793
|
|
|
1748
1794
|
else if (element == 'dropdown') {
|
|
1749
|
-
if (!attrs?.items || // There no are options to add
|
|
1795
|
+
if (!attrs?.items || // There no are options to add
|
|
1750
1796
|
!Array.isArray(attrs.items) || // It's not an array
|
|
1751
1797
|
!attrs.items.length) // The array is empty
|
|
1752
1798
|
attrs.items = [{ text: '🤖 chatgpt.js option', value: 'chatgpt.js option value' }]; // Set default dropdown entry
|
|
@@ -1761,7 +1807,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1761
1807
|
newElement.add(optionElement);
|
|
1762
1808
|
});
|
|
1763
1809
|
}
|
|
1764
|
-
|
|
1810
|
+
|
|
1765
1811
|
|
|
1766
1812
|
// Fix for blank background on dropdown elements
|
|
1767
1813
|
if (element == 'dropdown') newElement.style.backgroundColor = 'var(--gray-900, rgb(32, 33, 35))';
|
|
@@ -1862,7 +1908,7 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1862
1908
|
if (!outputLang) return console.error('outputLang (2nd) argument not supplied. Pass a language!');
|
|
1863
1909
|
for (let i = 0; i < arguments.length; i++) if (typeof arguments[i] !== 'string')
|
|
1864
1910
|
return console.error(`Argument ${ i + 1 } must be a string!`);
|
|
1865
|
-
chatgpt.send('Translate the following text to ' + outputLang
|
|
1911
|
+
chatgpt.send('Translate the following text to ' + outputLang
|
|
1866
1912
|
+ '. Only reply with the translation.\n\n' + text);
|
|
1867
1913
|
console.info('Translating text...');
|
|
1868
1914
|
await chatgpt.isIdle();
|
|
@@ -1872,14 +1918,19 @@ const chatgpt = { // eslint-disable-line no-redeclare
|
|
|
1872
1918
|
unminify() { chatgpt.code.unminify(); },
|
|
1873
1919
|
|
|
1874
1920
|
uuidv4() {
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
d =
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1921
|
+
try {
|
|
1922
|
+
// use native secure uuid generator when available
|
|
1923
|
+
return crypto.randomUUID();
|
|
1924
|
+
} catch(_e) {
|
|
1925
|
+
let d = new Date().getTime(); // get current timestamp in ms (to ensure UUID uniqueness)
|
|
1926
|
+
const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
1927
|
+
const r = ( // generate random nibble
|
|
1928
|
+
( d + (window.crypto.getRandomValues(new Uint32Array(1))[0] / (Math.pow(2, 32) - 1))*16)%16 | 0 );
|
|
1929
|
+
d = Math.floor(d/16); // correspond each UUID digit to unique 4-bit chunks of timestamp
|
|
1930
|
+
return ( c == 'x' ? r : (r&0x3|0x8) ).toString(16); // generate random hexadecimal digit
|
|
1931
|
+
});
|
|
1932
|
+
return uuid;
|
|
1933
|
+
}
|
|
1883
1934
|
},
|
|
1884
1935
|
|
|
1885
1936
|
writeCode() { chatgpt.code.write(); }
|
|
@@ -2011,7 +2062,7 @@ for (const prop in chatgpt) {
|
|
|
2011
2062
|
// Prefix console logs w/ '🤖 chatgpt.js >> '
|
|
2012
2063
|
const consolePrefix = '🤖 chatgpt.js >> ', ogError = console.error, ogInfo = console.info;
|
|
2013
2064
|
console.error = (...args) => {
|
|
2014
|
-
if (!args[0].startsWith(consolePrefix)) ogError(consolePrefix + args[0], ...args.slice(1));
|
|
2065
|
+
if (!args[0].startsWith(consolePrefix)) ogError(consolePrefix + args[0], ...args.slice(1));
|
|
2015
2066
|
else ogError(...args);
|
|
2016
2067
|
};
|
|
2017
2068
|
console.info = (msg) => {
|