@kudoai/chatgpt.js 3.8.3 → 3.8.5
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/LICENSE.md +1 -1
- package/README.md +12 -10
- package/chatgpt.js +50 -48
- package/dist/chatgpt.min.js +8 -8
- package/docs/README.md +12 -10
- package/docs/USERGUIDE.md +3 -3
- package/package.json +11 -10
- package/starters/chrome/extension/components/modals.js +53 -47
- package/starters/chrome/extension/content.js +14 -37
- package/starters/chrome/extension/lib/chatgpt.js +50 -48
- package/starters/chrome/extension/lib/dom.js +4 -1
- package/starters/chrome/extension/lib/feedback.js +33 -0
- package/starters/chrome/extension/lib/settings.js +8 -4
- package/starters/chrome/extension/manifest.json +1 -2
- package/starters/chrome/extension/popup/controller.js +62 -33
- package/starters/chrome/extension/popup/style.css +7 -5
- package/starters/chrome/extension/service-worker.js +12 -12
- package/starters/greasemonkey/chatgpt.js-greasemonkey-starter.user.js +3 -2
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
"name": "ChatGPT Extension",
|
|
4
4
|
"short_name": "ChatGPT 🧩",
|
|
5
5
|
"description": "A Chromium extension template to start using chatgpt.js like a boss!",
|
|
6
|
-
"version": "
|
|
7
|
-
"author": "KudoAI",
|
|
6
|
+
"version": "2026.1.4",
|
|
8
7
|
"homepage_url": "https://github.com/KudoAI/chatgpt.js-chrome-starter",
|
|
9
8
|
"icons": { "16": "icons/icon16.png", "32": "icons/icon32.png", "64": "icons/icon64.png", "128": "icons/icon128.png" },
|
|
10
9
|
"permissions": ["activeTab", "storage"],
|
|
@@ -8,61 +8,89 @@
|
|
|
8
8
|
for (const resource of ['components/icons.js', 'lib/dom.js', 'lib/settings.js'])
|
|
9
9
|
await import(chrome.runtime.getURL(resource))
|
|
10
10
|
|
|
11
|
-
// Init
|
|
11
|
+
// Init DATA
|
|
12
12
|
window.env = {
|
|
13
13
|
site: new URL((await chrome.tabs.query({ active: true, currentWindow: true }))[0].url)
|
|
14
14
|
.hostname.split('.').slice(-2, -1)[0], // extract 2nd-level domain
|
|
15
15
|
menu: { isDark: document.documentElement.classList.contains('dark') }
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
// Import DATA
|
|
19
17
|
;({ app: window.app } = await chrome.storage.local.get('app'))
|
|
20
18
|
|
|
21
19
|
// Define FUNCTIONS
|
|
22
20
|
|
|
23
21
|
function createMenuEntry(entryData) {
|
|
24
|
-
|
|
25
|
-
// Assemble elems
|
|
26
22
|
const entry = {
|
|
27
23
|
div: dom.create.elem('div', {
|
|
28
24
|
id: entryData.key, class: 'menu-entry highlight-on-hover', title: entryData.helptip || '' }),
|
|
29
25
|
leftElem: dom.create.elem('div', { class: `menu-icon ${ entryData.type || '' }`}),
|
|
30
|
-
label: dom.create.elem('span')
|
|
26
|
+
label: dom.create.elem('span', { textContent: entryData.label })
|
|
31
27
|
}
|
|
32
|
-
entry.label.textContent = entryData.label
|
|
33
28
|
entry.div.append(entry.leftElem, entry.label)
|
|
29
|
+
|
|
34
30
|
if (entryData.type == 'toggle') { // add track to left, init knob pos
|
|
35
31
|
entry.leftElem.append(dom.create.elem('span', { class: 'track' }))
|
|
36
32
|
entry.leftElem.classList.toggle('on', settings.typeIsEnabled(entryData.key))
|
|
33
|
+
|
|
37
34
|
} else { // add symbol to left, append status to right
|
|
38
35
|
entry.leftElem.textContent = entryData.symbol || '⚙️' ; entry.label.style.flexGrow = 1
|
|
39
36
|
if (entryData.status) entry.label.textContent += ` — ${entryData.status}`
|
|
40
37
|
if (entryData.type == 'link') {
|
|
41
38
|
entry.label.after(entry.rightElem = dom.create.elem('div', { class: 'menu-right-elem' }))
|
|
42
|
-
entry.
|
|
39
|
+
if (entryData.favicon) entry.favicon = dom.create.elem('img', { width: 15,
|
|
40
|
+
src: typeof entryData.favicon == 'string' ? entryData.favicon
|
|
41
|
+
: `https://www.google.com/s2/favicons?domain=${new URL(entryData.url).hostname}` })
|
|
42
|
+
entry.openIcon = icons.create({ key: 'open', size: 17, fill: 'black' })
|
|
43
|
+
entry.rightElem.append(entry.favicon || entry.openIcon)
|
|
44
|
+
if (entry.favicon) entry.rightElem.onmouseenter = entry.rightElem.onmouseleave = ({ type }) =>
|
|
45
|
+
entry.rightElem.firstChild.replaceWith(entry[type == 'mouseenter' ? 'openIcon' : 'favicon'])
|
|
43
46
|
}
|
|
44
47
|
}
|
|
45
|
-
|
|
48
|
+
|
|
49
|
+
if (entryData.type == 'category') // append drop-down caret
|
|
46
50
|
entry.div.append(icons.create({ key: 'caretDown', size: 11, class: 'menu-caret menu-right-elem' }))
|
|
51
|
+
|
|
47
52
|
else if (entryData.type == 'slider') { // append slider, add listeners, remove .highlight-on-hover
|
|
48
|
-
|
|
49
|
-
|
|
53
|
+
const minVal = entryData.min ?? 0, maxVal = entryData.max ?? 100
|
|
54
|
+
|
|
55
|
+
// Create/append slider elems
|
|
56
|
+
entry.div.append(entry.slider = dom.create.elem('input', { class: 'slider', type: 'range',
|
|
57
|
+
min: minVal, max: maxVal, value: config[entryData.key] }))
|
|
58
|
+
entry.div.classList.remove('highlight-on-hover')
|
|
50
59
|
if (entryData.step || env.browser.isFF) // use val from entryData or default to 2% in FF for being laggy
|
|
51
60
|
entry.slider.step = entryData.step || ( 0.02 * entry.slider.max - entry.slider.min )
|
|
52
61
|
entry.label.textContent += `: ${entry.slider.value}${ entryData.labelSuffix || '' }`
|
|
62
|
+
entry.label.append(entry.editLink = dom.create.elem('span', {
|
|
63
|
+
class: 'edit-link', role: 'button', tabindex: '0', 'aria-label': entryData.helptip, textContent: 'Edit'
|
|
64
|
+
}))
|
|
53
65
|
entry.slider.style.setProperty('--track-fill-percent', `${ entry.slider.value / entry.slider.max *100 }%`)
|
|
66
|
+
|
|
67
|
+
// Add listeners
|
|
68
|
+
entry.editLink.onclick = () => {
|
|
69
|
+
const promptMsg = `Enter new value for ${entryData.label} (between ${minVal}–${maxVal}):`,
|
|
70
|
+
userVal = prompt(promptMsg, entry.slider.value)
|
|
71
|
+
if (userVal == null) return // user cancelled so do nothing
|
|
72
|
+
if (!/\d/.test(userVal)) return alert(`Enter a valid number between ${minVal} and ${maxVal}!`)
|
|
73
|
+
let validVal = parseInt(userVal.replace(/\D/g, '')) ; if (isNaN(validVal)) return
|
|
74
|
+
validVal = Math.max(minVal, Math.min(maxVal, validVal))
|
|
75
|
+
entry.slider.value = validVal ; settings.save(entryData.key, validVal)
|
|
76
|
+
sync.configToUI({ updatedKey: entryData.key })
|
|
77
|
+
entry.label.textContent = `${entryData.label}: ${validVal}${ entryData.labelSuffix || '' }`
|
|
78
|
+
entry.label.append(entry.editLink)
|
|
79
|
+
entry.slider.style.setProperty('--track-fill-percent', `${ validVal / entry.slider.max *100 }%`)
|
|
80
|
+
}
|
|
54
81
|
entry.slider.oninput = ({ target: { value }}) => { // update label/color
|
|
55
82
|
settings.save(entryData.key, parseInt(value)) ; sync.configToUI({ updatedKey: entryData.key })
|
|
56
83
|
entry.label.textContent = `${entryData.label}: ${value}${ entryData.labelSuffix || '' }`
|
|
84
|
+
entry.label.append(entry.editLink)
|
|
57
85
|
entry.slider.style.setProperty('--track-fill-percent', `${ value / entry.slider.max *100 }%`)
|
|
58
86
|
}
|
|
59
|
-
entry.div.onwheel =
|
|
60
|
-
entry.slider.value = parseInt(entry.slider.value) -Math.sign(
|
|
87
|
+
entry.div.onwheel = ({ deltaY }) => { // move slider by 2 steps
|
|
88
|
+
entry.slider.value = parseInt(entry.slider.value) - Math.sign(deltaY) *2
|
|
61
89
|
entry.slider.dispatchEvent(new Event('input'))
|
|
62
90
|
}
|
|
63
|
-
entry.div.append(entry.slider) ; entry.div.classList.remove('highlight-on-hover')
|
|
64
91
|
}
|
|
65
|
-
|
|
92
|
+
|
|
93
|
+
if (entryData.dependencies) { // hide/show according to toggle state
|
|
66
94
|
const toDisable = Object.values(entryData.dependencies).flat().some(dep => !settings.typeIsEnabled(dep))
|
|
67
95
|
Object.assign(entry.div.style, {
|
|
68
96
|
transition: '', minHeight: 'auto', opacity: +!toDisable,
|
|
@@ -83,8 +111,8 @@
|
|
|
83
111
|
entry.leftElem.classList.toggle('on')
|
|
84
112
|
settings.save(entryData.key, !config[entryData.key])
|
|
85
113
|
sync.configToUI({ updatedKey: entryData.key })
|
|
86
|
-
requestAnimationFrame(() => notify(
|
|
87
|
-
|
|
114
|
+
requestAnimationFrame(() => notify(
|
|
115
|
+
`${entryData.label} ${['OFF', 'ON'][+settings.typeIsEnabled(entryData.key)]}`))
|
|
88
116
|
},
|
|
89
117
|
link: () => { open(entryData.url) ; close() }
|
|
90
118
|
})[entryData.type]()
|
|
@@ -99,8 +127,7 @@
|
|
|
99
127
|
for (const [ctrlKey, ctrlData] of Object.entries({ ...settings.categories, ...settings.controls }))
|
|
100
128
|
if (Object.values(ctrlData.dependencies || {}).flat().includes(entryData.key)) {
|
|
101
129
|
const depDiv = document.querySelector(`div#${ctrlKey}`) ; if (!depDiv) continue
|
|
102
|
-
const
|
|
103
|
-
ctgChildren = ctgChildrenDiv.querySelectorAll('.menu-entry'),
|
|
130
|
+
const ctgChildren = depDiv.closest('.categorized-entries').querySelectorAll('.menu-entry'),
|
|
104
131
|
toDisable = !settings.typeIsEnabled(entryData.key)
|
|
105
132
|
requestAnimationFrame(() => Object.assign(depDiv.closest('.categorized-entries').style, {
|
|
106
133
|
height: `${dom.get.computedHeight(ctgChildren)}px`,
|
|
@@ -144,7 +171,7 @@
|
|
|
144
171
|
if (elem.id && (elem.matches(`#${elem.id}:has(> div.link)`) || elem.id == 'aboutEntry'))
|
|
145
172
|
return // never disable link/About entries
|
|
146
173
|
elem.style.transition = config.extensionDisabled ? '' : 'opacity 0.15s ease-in'
|
|
147
|
-
const toDisable = config.
|
|
174
|
+
const toDisable = config.extensionDisabled || !depIsEnabled(elem.id)
|
|
148
175
|
if (elem.classList.contains('categorized-entries')) { // fade category strip
|
|
149
176
|
elem.style.transition = toDisable ? 'none' : 'var(--border-transition)'
|
|
150
177
|
elem.style.borderImage = elem.style.borderImage.replace(
|
|
@@ -207,7 +234,6 @@
|
|
|
207
234
|
masterToggle.div.append(masterToggle.switch) ; masterToggle.switch.append(masterToggle.track)
|
|
208
235
|
await settings.load('extensionDisabled') ; masterToggle.switch.classList.toggle('on', !config.extensionDisabled)
|
|
209
236
|
masterToggle.div.onclick = () => {
|
|
210
|
-
env.extensionWasDisabled = config.extensionDisabled
|
|
211
237
|
masterToggle.switch.classList.toggle('on') ; settings.save('extensionDisabled', !config.extensionDisabled)
|
|
212
238
|
Object.keys(sync).forEach(key => sync[key]()) // sync fade + storage to UI
|
|
213
239
|
notify(`${app.name} ${ this.checked ? 'ON' : 'OFF' }`)
|
|
@@ -228,17 +254,17 @@
|
|
|
228
254
|
Object.values(categorizedCtrls.general || {}).forEach(ctrl => menuEntriesDiv.append(createMenuEntry(ctrl)))
|
|
229
255
|
|
|
230
256
|
// Create/append categorized controls
|
|
231
|
-
Object.entries(
|
|
232
|
-
if (
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
if (
|
|
236
|
-
const [r, g, b] =
|
|
257
|
+
Object.entries(settings.categories).forEach(([key, category]) => {
|
|
258
|
+
if (!categorizedCtrls[key]) return
|
|
259
|
+
category.key = key ; category.type = 'category'
|
|
260
|
+
const ctgChildrenDiv = dom.create.elem('div', { class: 'categorized-entries' })
|
|
261
|
+
if (category.color) { // color the stripe
|
|
262
|
+
const [r, g, b] = category.color.match(/\w\w/g).map(v => parseInt(v, 16))
|
|
237
263
|
ctgChildrenDiv.style.borderImage = `linear-gradient(transparent, rgba(${r},${g},${b},${
|
|
238
264
|
env.menu.isDark ? 0.5 : 1 })) 30 100% ${ env.menu.isDark ? '/ 100' : '' }`
|
|
239
265
|
}
|
|
240
|
-
menuEntriesDiv.append(createMenuEntry(
|
|
241
|
-
Object.values(
|
|
266
|
+
menuEntriesDiv.append(createMenuEntry(category), ctgChildrenDiv)
|
|
267
|
+
Object.values(categorizedCtrls[key]).forEach(ctrl => ctgChildrenDiv.append(createMenuEntry(ctrl)))
|
|
242
268
|
})
|
|
243
269
|
}
|
|
244
270
|
|
|
@@ -261,15 +287,18 @@
|
|
|
261
287
|
aboutEntry.div.onclick = () => { chrome.runtime.sendMessage({ action: 'showAbout' }) ; close() }
|
|
262
288
|
|
|
263
289
|
// Create/append CHATGPT entry
|
|
264
|
-
const
|
|
290
|
+
const [activeTab] = await chrome.tabs.query({ active: true, currentWindow: true }),
|
|
265
291
|
chatgptURL = chrome.runtime.getManifest().content_scripts[0].matches.map(url => url.replace(/\/\*$/, ''))
|
|
266
|
-
if (!
|
|
267
|
-
|
|
292
|
+
if (!activeTab.url.includes(chatgptURL))
|
|
293
|
+
footer.before(createMenuEntry({
|
|
294
|
+
key: 'chatgptEntry', type: 'link', symbol: '🤖', url: chatgptURL, helptip: chatgptURL, label: 'Open ChatGPT',
|
|
295
|
+
favicon: 'data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22180%22%20height=%22180%22%20fill=%22none%22%3E%3Cstyle%3E:root%7B--primary-fill:%23000;--secondary-fill:%23fff;%7D@media%20(prefers-color-scheme:dark)%7B:root%7B--primary-fill:%23fff;--secondary-fill:%23000;%7D%7D%3C/style%3E%3Cg%20clip-path=%22url(%23a)%22%3E%3Crect%20width=%22180%22%20height=%22180%22%20fill=%22var(--primary-fill)%22%20rx=%2290%22/%3E%3Cg%20clip-path=%22url(%23b)%22%3E%3Cpath%20fill=%22var(--secondary-fill)%22%20d=%22M75.91%2073.628V62.232c0-.96.36-1.68%201.199-2.16l22.912-13.194c3.119-1.8%206.838-2.639%2010.676-2.639%2014.394%200%2023.511%2011.157%2023.511%2023.032%200%20.839%200%201.799-.12%202.758l-23.752-13.914c-1.439-.84-2.879-.84-4.318%200L75.91%2073.627Zm53.499%2044.383v-27.23c0-1.68-.72-2.88-2.159-3.719L97.142%2069.55l9.836-5.638c.839-.48%201.559-.48%202.399%200l22.912%2013.195c6.598%203.839%2011.035%2011.995%2011.035%2019.912%200%209.116-5.397%2017.513-13.915%2020.992v.001Zm-60.577-23.99-9.836-5.758c-.84-.48-1.2-1.2-1.2-2.16v-26.39c0-12.834%209.837-22.55%2023.152-22.55%205.039%200%209.716%201.679%2013.676%204.678L70.993%2055.516c-1.44.84-2.16%202.039-2.16%203.719v34.787-.002Zm21.173%2012.234L75.91%2098.339V81.546l14.095-7.917%2014.094%207.917v16.793l-14.094%207.916Zm9.056%2036.467c-5.038%200-9.716-1.68-13.675-4.678l23.631-13.676c1.439-.839%202.159-2.038%202.159-3.718V85.863l9.956%205.757c.84.48%201.2%201.2%201.2%202.16v26.389c0%2012.835-9.957%2022.552-23.27%2022.552v.001Zm-28.43-26.75L47.72%20102.778c-6.599-3.84-11.036-11.996-11.036-19.913%200-9.236%205.518-17.513%2014.034-20.992v27.35c0%201.68.72%202.879%202.16%203.718l29.989%2017.393-9.837%205.638c-.84.48-1.56.48-2.399%200Zm-1.318%2019.673c-13.555%200-23.512-10.196-23.512-22.792%200-.959.12-1.919.24-2.879l23.63%2013.675c1.44.84%202.88.84%204.32%200l30.108-17.392v11.395c0%20.96-.361%201.68-1.2%202.16l-22.912%2013.194c-3.119%201.8-6.837%202.639-10.675%202.639Zm29.748%2014.274c14.515%200%2026.63-10.316%2029.39-23.991%2013.434-3.479%2022.071-16.074%2022.071-28.91%200-8.396-3.598-16.553-10.076-22.43.6-2.52.96-5.039.96-7.557%200-17.153-13.915-29.99-29.989-29.99-3.239%200-6.358.48-9.477%201.56-5.398-5.278-12.835-8.637-20.992-8.637-14.515%200-26.63%2010.316-29.39%2023.991-13.434%203.48-22.07%2016.074-22.07%2028.91%200%208.396%203.598%2016.553%2010.075%2022.431-.6%202.519-.96%205.038-.96%207.556%200%2017.154%2013.915%2029.989%2029.99%2029.989%203.238%200%206.357-.479%209.476-1.559%205.397%205.278%2012.835%208.637%2020.992%208.637Z%22/%3E%3C/g%3E%3C/g%3E%3Cdefs%3E%3CclipPath%20id=%22a%22%3E%3Cpath%20d=%22M0%200h180v180H0z%22/%3E%3C/clipPath%3E%3CclipPath%20id=%22b%22%3E%3Cpath%20d=%22M29.487%2029.964h121.035v119.954H29.487z%22/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E'
|
|
296
|
+
}))
|
|
268
297
|
|
|
269
298
|
// Create/append LATEST CHANGES entry
|
|
270
299
|
const latestChangesURL = `${app.urls.github}/commits`
|
|
271
300
|
footer.before(createMenuEntry({
|
|
272
|
-
key: 'latestChangesEntry', type: 'link', symbol: '🚀',
|
|
301
|
+
key: 'latestChangesEntry', type: 'link', symbol: '🚀', favicon: true,
|
|
273
302
|
label: 'Latest Changes...', url: latestChangesURL, helptip: latestChangesURL
|
|
274
303
|
}))
|
|
275
304
|
|
|
@@ -8,13 +8,12 @@ body {
|
|
|
8
8
|
width: 268px ; margin: 0 ; font-size: .905rem ;
|
|
9
9
|
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
10
10
|
"PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", sans-serif ;
|
|
11
|
-
background-image: linear-gradient(180deg, #b6ebff -
|
|
11
|
+
background-image: linear-gradient(180deg, #b6ebff -96px, white 65px)
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
/* Color/fade mods */
|
|
15
15
|
.highlight-on-hover:hover { background: var(--entry-highlighted-bg) }
|
|
16
|
-
.highlight-on-hover:hover span:not(.track),
|
|
17
|
-
filter: invert(1) } /* invert setting labels on hover */
|
|
16
|
+
.highlight-on-hover:hover :where(span:not(.track), svg) { filter: invert(1) } /* invert setting labels on hover */
|
|
18
17
|
.disabled { opacity: 0.3 !important ; pointer-events: none }
|
|
19
18
|
|
|
20
19
|
/* Loader */
|
|
@@ -45,7 +44,7 @@ header {
|
|
|
45
44
|
border-bottom: solid 1px lightgrey ; padding: 5px 5px 5px 0 ; margin: 0 ;
|
|
46
45
|
height: 38px ; display: flex ; align-items: center }
|
|
47
46
|
.logo { margin: 0 8px 0 12px ; position: relative ; top: 3px }
|
|
48
|
-
.menu-title { font-size:
|
|
47
|
+
.menu-title { font-size: 1rem ; font-weight: 600 ; padding: 4px }
|
|
49
48
|
.master-toggle { margin-left: auto ; display: flex }
|
|
50
49
|
|
|
51
50
|
/* Menu item elements */
|
|
@@ -84,6 +83,8 @@ div.menu-entry > input.slider {
|
|
|
84
83
|
border: 4px solid var(--thumb-border) ; border-radius: 16px ; cursor: ew-resize ; transition: transform 0.05s ease
|
|
85
84
|
}
|
|
86
85
|
.slider::-webkit-slider-thumb:hover { transform: scaleX(1.325) }
|
|
86
|
+
.edit-link { text-transform: uppercase ; font-size: 0.65em ; margin-left: 0.75em ; opacity: 0.5 ; cursor: pointer }
|
|
87
|
+
.edit-link:hover { transition: opacity 0.1s ease-in-out ; opacity: 1 }
|
|
87
88
|
|
|
88
89
|
/* Toggle elements */
|
|
89
90
|
.toggle .track {
|
|
@@ -105,7 +106,7 @@ div#about > div.menu-icon { padding: 8px 10px 8px 11px }
|
|
|
105
106
|
mask-image: var(--mask) ; -webkit-mask-image: var(--mask) /* eslint-disable-line */
|
|
106
107
|
}
|
|
107
108
|
.ticker-em { color: green } .highlight-on-hover:hover .ticker-em { color: #28ee28 }
|
|
108
|
-
.ticker > div { animation: ticker linear
|
|
109
|
+
.ticker > div { animation: ticker linear 85s infinite }
|
|
109
110
|
@keyframes ticker { 0% { transform: translateX(100%) } 100% { transform: translateX(-2000%) }}
|
|
110
111
|
|
|
111
112
|
/* Footer */
|
|
@@ -139,6 +140,7 @@ html.dark .menu-icon svg, html.dark .menu-right-elem, html.dark .menu-right-elem
|
|
|
139
140
|
html.dark .menu-icon img { filter: brightness(0) invert(1) }
|
|
140
141
|
html.dark .menu-icon:hover img { filter: none }
|
|
141
142
|
html.dark .ticker-em { color: #28ee28 } html.dark .highlight-on-hover:hover .ticker-em { color: green }
|
|
143
|
+
html.dark #chatgptEntry:hover img { filter: invert(1) } /* to white favicon for legibility */
|
|
142
144
|
|
|
143
145
|
/* Non-baseline features */
|
|
144
146
|
@supports (cursor: pointer) { .highlight-on-hover:hover, .toggle .track, .chatgptjs-logo { cursor: pointer }}
|
|
@@ -8,33 +8,33 @@ chrome.storage.local.set({ app: {
|
|
|
8
8
|
urls: {
|
|
9
9
|
chatgptjs: 'https://chatgptjs.org',
|
|
10
10
|
contributors: 'https://docs.chatgptjs.org/#-contributors',
|
|
11
|
-
|
|
11
|
+
github: 'https://github.com/KudoAI/chatgpt.js-chrome-starter',
|
|
12
12
|
relatedExtensions: 'https://aiwebextensions.com',
|
|
13
13
|
support: 'https://github.com/KudoAI/chatgpt.js-chrome-starter/issues'
|
|
14
14
|
}
|
|
15
15
|
}}) // save to Chrome storage
|
|
16
16
|
|
|
17
17
|
// Launch CHATGPT on install
|
|
18
|
-
chrome.runtime.onInstalled.addListener(
|
|
19
|
-
if (
|
|
18
|
+
chrome.runtime.onInstalled.addListener(({ reason }) => {
|
|
19
|
+
if (reason == 'install') // to exclude updates
|
|
20
20
|
chrome.tabs.create({ url: chatgptURL })
|
|
21
21
|
})
|
|
22
22
|
|
|
23
23
|
// Sync SETTINGS to activated tabs
|
|
24
|
-
chrome.tabs.onActivated.addListener(
|
|
25
|
-
chrome.tabs.sendMessage(
|
|
24
|
+
chrome.tabs.onActivated.addListener(({ tabId }) =>
|
|
25
|
+
chrome.tabs.sendMessage(tabId, { action: 'syncConfigToUI' }))
|
|
26
26
|
|
|
27
27
|
// Show ABOUT modal on ChatGPT when toolbar button clicked
|
|
28
|
-
chrome.runtime.onMessage.addListener(async
|
|
29
|
-
if (
|
|
28
|
+
chrome.runtime.onMessage.addListener(async ({ action }) => {
|
|
29
|
+
if (action == 'showAbout') {
|
|
30
30
|
const [activeTab] = await chrome.tabs.query({ active: true, currentWindow: true })
|
|
31
31
|
const chatgptTab = new URL(activeTab.url).hostname == 'chatgpt.com' ? activeTab
|
|
32
|
-
|
|
32
|
+
: await chrome.tabs.create({ url: chatgptURL })
|
|
33
33
|
if (activeTab != chatgptTab) await new Promise(resolve => // after new tab loads
|
|
34
|
-
chrome.tabs.onUpdated.addListener(function loadedListener(tabId,
|
|
35
|
-
if (tabId == chatgptTab.id &&
|
|
36
|
-
chrome.tabs.onUpdated.removeListener(loadedListener) ; setTimeout(resolve,
|
|
34
|
+
chrome.tabs.onUpdated.addListener(function loadedListener(tabId, { status }) {
|
|
35
|
+
if (tabId == chatgptTab.id && status == 'complete') {
|
|
36
|
+
chrome.tabs.onUpdated.removeListener(loadedListener) ; setTimeout(resolve, 1500)
|
|
37
37
|
}}))
|
|
38
|
-
chrome.tabs.sendMessage(chatgptTab.id, { action: 'showAbout' })
|
|
38
|
+
chrome.tabs.sendMessage(chatgptTab.id, { action: 'showAbout', source: 'service-worker.js' })
|
|
39
39
|
}
|
|
40
40
|
})
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
// @description A Greasemonkey template to start using chatgpt.js like a boss
|
|
4
4
|
// @author chatgpt.js
|
|
5
5
|
// @namespace https://chatgpt.js.org
|
|
6
|
-
// @version
|
|
6
|
+
// @version 2026.1.4
|
|
7
7
|
// @license MIT
|
|
8
8
|
// @icon data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='180'%20height='180'%20fill='none'%3e%3cstyle%3e%20:root%20{%20--primary-fill:%20%23000;%20--secondary-fill:%20%23fff;%20}%20@media%20(prefers-color-scheme:%20dark)%20{%20:root%20{%20--primary-fill:%20%23fff;%20--secondary-fill:%20%23000;%20}%20}%20%3c/style%3e%3cg%20clip-path='url(%23a)'%3e%3crect%20width='180'%20height='180'%20fill='var(--primary-fill)'%20rx='90'%20/%3e%3cg%20clip-path='url(%23b)'%3e%3cpath%20fill='var(--secondary-fill)'%20d='M75.91%2073.628V62.232c0-.96.36-1.68%201.199-2.16l22.912-13.194c3.119-1.8%206.838-2.639%2010.676-2.639%2014.394%200%2023.511%2011.157%2023.511%2023.032%200%20.839%200%201.799-.12%202.758l-23.752-13.914c-1.439-.84-2.879-.84-4.318%200L75.91%2073.627Zm53.499%2044.383v-27.23c0-1.68-.72-2.88-2.159-3.719L97.142%2069.55l9.836-5.638c.839-.48%201.559-.48%202.399%200l22.912%2013.195c6.598%203.839%2011.035%2011.995%2011.035%2019.912%200%209.116-5.397%2017.513-13.915%2020.992v.001Zm-60.577-23.99-9.836-5.758c-.84-.48-1.2-1.2-1.2-2.16v-26.39c0-12.834%209.837-22.55%2023.152-22.55%205.039%200%209.716%201.679%2013.676%204.678L70.993%2055.516c-1.44.84-2.16%202.039-2.16%203.719v34.787-.002Zm21.173%2012.234L75.91%2098.339V81.546l14.095-7.917%2014.094%207.917v16.793l-14.094%207.916Zm9.056%2036.467c-5.038%200-9.716-1.68-13.675-4.678l23.631-13.676c1.439-.839%202.159-2.038%202.159-3.718V85.863l9.956%205.757c.84.48%201.2%201.2%201.2%202.16v26.389c0%2012.835-9.957%2022.552-23.27%2022.552v.001Zm-28.43-26.75L47.72%20102.778c-6.599-3.84-11.036-11.996-11.036-19.913%200-9.236%205.518-17.513%2014.034-20.992v27.35c0%201.68.72%202.879%202.16%203.718l29.989%2017.393-9.837%205.638c-.84.48-1.56.48-2.399%200Zm-1.318%2019.673c-13.555%200-23.512-10.196-23.512-22.792%200-.959.12-1.919.24-2.879l23.63%2013.675c1.44.84%202.88.84%204.32%200l30.108-17.392v11.395c0%20.96-.361%201.68-1.2%202.16l-22.912%2013.194c-3.119%201.8-6.837%202.639-10.675%202.639Zm29.748%2014.274c14.515%200%2026.63-10.316%2029.39-23.991%2013.434-3.479%2022.071-16.074%2022.071-28.91%200-8.396-3.598-16.553-10.076-22.43.6-2.52.96-5.039.96-7.557%200-17.153-13.915-29.99-29.989-29.99-3.239%200-6.358.48-9.477%201.56-5.398-5.278-12.835-8.637-20.992-8.637-14.515%200-26.63%2010.316-29.39%2023.991-13.434%203.48-22.07%2016.074-22.07%2028.91%200%208.396%203.598%2016.553%2010.075%2022.431-.6%202.519-.96%205.038-.96%207.556%200%2017.154%2013.915%2029.989%2029.99%2029.989%203.238%200%206.357-.479%209.476-1.559%205.397%205.278%2012.835%208.637%2020.992%208.637Z'%20/%3e%3c/g%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='a'%3e%3cpath%20d='M0%200h180v180H0z'%20/%3e%3c/clipPath%3e%3cclipPath%20id='b'%3e%3cpath%20d='M29.487%2029.964h121.035v119.954H29.487z'%20/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e
|
|
9
9
|
// @icon64 data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='180'%20height='180'%20fill='none'%3e%3cstyle%3e%20:root%20{%20--primary-fill:%20%23000;%20--secondary-fill:%20%23fff;%20}%20@media%20(prefers-color-scheme:%20dark)%20{%20:root%20{%20--primary-fill:%20%23fff;%20--secondary-fill:%20%23000;%20}%20}%20%3c/style%3e%3cg%20clip-path='url(%23a)'%3e%3crect%20width='180'%20height='180'%20fill='var(--primary-fill)'%20rx='90'%20/%3e%3cg%20clip-path='url(%23b)'%3e%3cpath%20fill='var(--secondary-fill)'%20d='M75.91%2073.628V62.232c0-.96.36-1.68%201.199-2.16l22.912-13.194c3.119-1.8%206.838-2.639%2010.676-2.639%2014.394%200%2023.511%2011.157%2023.511%2023.032%200%20.839%200%201.799-.12%202.758l-23.752-13.914c-1.439-.84-2.879-.84-4.318%200L75.91%2073.627Zm53.499%2044.383v-27.23c0-1.68-.72-2.88-2.159-3.719L97.142%2069.55l9.836-5.638c.839-.48%201.559-.48%202.399%200l22.912%2013.195c6.598%203.839%2011.035%2011.995%2011.035%2019.912%200%209.116-5.397%2017.513-13.915%2020.992v.001Zm-60.577-23.99-9.836-5.758c-.84-.48-1.2-1.2-1.2-2.16v-26.39c0-12.834%209.837-22.55%2023.152-22.55%205.039%200%209.716%201.679%2013.676%204.678L70.993%2055.516c-1.44.84-2.16%202.039-2.16%203.719v34.787-.002Zm21.173%2012.234L75.91%2098.339V81.546l14.095-7.917%2014.094%207.917v16.793l-14.094%207.916Zm9.056%2036.467c-5.038%200-9.716-1.68-13.675-4.678l23.631-13.676c1.439-.839%202.159-2.038%202.159-3.718V85.863l9.956%205.757c.84.48%201.2%201.2%201.2%202.16v26.389c0%2012.835-9.957%2022.552-23.27%2022.552v.001Zm-28.43-26.75L47.72%20102.778c-6.599-3.84-11.036-11.996-11.036-19.913%200-9.236%205.518-17.513%2014.034-20.992v27.35c0%201.68.72%202.879%202.16%203.718l29.989%2017.393-9.837%205.638c-.84.48-1.56.48-2.399%200Zm-1.318%2019.673c-13.555%200-23.512-10.196-23.512-22.792%200-.959.12-1.919.24-2.879l23.63%2013.675c1.44.84%202.88.84%204.32%200l30.108-17.392v11.395c0%20.96-.361%201.68-1.2%202.16l-22.912%2013.194c-3.119%201.8-6.837%202.639-10.675%202.639Zm29.748%2014.274c14.515%200%2026.63-10.316%2029.39-23.991%2013.434-3.479%2022.071-16.074%2022.071-28.91%200-8.396-3.598-16.553-10.076-22.43.6-2.52.96-5.039.96-7.557%200-17.153-13.915-29.99-29.989-29.99-3.239%200-6.358.48-9.477%201.56-5.398-5.278-12.835-8.637-20.992-8.637-14.515%200-26.63%2010.316-29.39%2023.991-13.434%203.48-22.07%2016.074-22.07%2028.91%200%208.396%203.598%2016.553%2010.075%2022.431-.6%202.519-.96%205.038-.96%207.556%200%2017.154%2013.915%2029.989%2029.99%2029.989%203.238%200%206.357-.479%209.476-1.559%205.397%205.278%2012.835%208.637%2020.992%208.637Z'%20/%3e%3c/g%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='a'%3e%3cpath%20d='M0%200h180v180H0z'%20/%3e%3c/clipPath%3e%3cclipPath%20id='b'%3e%3cpath%20d='M29.487%2029.964h121.035v119.954H29.487z'%20/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e
|
|
10
10
|
// @match *://chatgpt.com/*
|
|
11
|
-
// @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.8.
|
|
11
|
+
// @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.8.5/dist/chatgpt.min.js
|
|
12
12
|
// @grant GM_getValue
|
|
13
13
|
// @grant GM_setValue
|
|
14
14
|
// @noframes
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
// NOTE: This script relies on the powerful chatgpt.js library @ https://chatgpt.js.org © 2023–2025 KudoAI & contributors under the MIT license
|
|
20
20
|
|
|
21
21
|
(async () => {
|
|
22
|
+
'use strict'
|
|
22
23
|
|
|
23
24
|
// Init config
|
|
24
25
|
const config = { prefix: 'chatgptScript' } ; loadSetting('skipAlert')
|