@kudoai/chatgpt.js 3.4.0 → 3.5.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.
@@ -99,7 +99,8 @@ const chatgpt = {
99
99
  chatgpt.draggableElem = event.currentTarget
100
100
  chatgpt.draggableElem.style.cursor = 'grabbing'
101
101
  event.preventDefault(); // prevent sub-elems like icons being draggable
102
- ['mousemove', 'mouseup'].forEach(event => document.addEventListener(event, handlers.drag[event]))
102
+ ['mousemove', 'mouseup'].forEach(eventType =>
103
+ document.addEventListener(eventType, handlers.drag[eventType]))
103
104
  const draggableElemRect = chatgpt.draggableElem.getBoundingClientRect()
104
105
  handlers.drag.offsetX = event.clientX - draggableElemRect.left +21
105
106
  handlers.drag.offsetY = event.clientY - draggableElemRect.top +12
@@ -114,8 +115,8 @@ const chatgpt = {
114
115
 
115
116
  mouseup() { // remove listeners, reset chatgpt.draggableElem
116
117
  chatgpt.draggableElem.style.cursor = 'inherit';
117
- ['mousemove', 'mouseup'].forEach(event =>
118
- document.removeEventListener(event, handlers.drag[event]))
118
+ ['mousemove', 'mouseup'].forEach(eventType =>
119
+ document.removeEventListener(eventType, handlers.drag[eventType]))
119
120
  chatgpt.draggableElem = null
120
121
  }
121
122
  }
@@ -130,7 +131,7 @@ const chatgpt = {
130
131
  modalMessage = document.createElement('p');
131
132
 
132
133
  // Create/append/update modal style (if missing or outdated)
133
- const thisUpdated = 1734685032942; // timestamp of last edit for this file's `modalStyle`
134
+ const thisUpdated = 1735475757891 // timestamp of last edit for this file's `modalStyle`
134
135
  let modalStyle = document.querySelector('#chatgpt-modal-style'); // try to select existing style
135
136
  if (!modalStyle || parseInt(modalStyle.getAttribute('last-updated'), 10) < thisUpdated) { // if missing or outdated
136
137
  if (!modalStyle) { // outright missing, create/id/attr/append it first
@@ -163,6 +164,7 @@ const chatgpt = {
163
164
  + ' -webkit-user-select: none ; -moz-user-select: none ; -ms-user-select: none ; user-select: none ; }'
164
165
  + '.chatgpt-modal h2 { margin-bottom: 9px }'
165
166
  + `.chatgpt-modal a { color: ${ scheme == 'dark' ? '#00cfff' : '#1e9ebb' }}`
167
+ + '.chatgpt-modal a:hover { text-decoration: underline }'
166
168
  + '.chatgpt-modal.animated > div { z-index: 13456 ; opacity: 0.98 ; transform: translateX(0) translateY(0) }'
167
169
  + '@keyframes alert-zoom-fade-out {'
168
170
  + '0% { opacity: 1 } 50% { opacity: 0.25 ; transform: scale(1.05) }'
@@ -193,12 +195,12 @@ const chatgpt = {
193
195
  + '.chatgpt-modal .checkbox-group label {'
194
196
  + 'font-size: .7rem ; margin: -.04rem 0 0px .3rem ;'
195
197
  + `color: ${ scheme == 'dark' ? '#e1e1e1' : '#1e1e1e' }}`
196
- + '.chatgpt-modal input[type="checkbox"] { transform: scale(0.7) ;'
198
+ + '.chatgpt-modal input[type=checkbox] { transform: scale(0.7) ;'
197
199
  + `border: 1px solid ${ scheme == 'dark' ? 'white' : 'black' }}`
198
- + '.chatgpt-modal input[type="checkbox"]:checked {'
200
+ + '.chatgpt-modal input[type=checkbox]:checked {'
199
201
  + `border: 1px solid ${ scheme == 'dark' ? 'white' : 'black' } ;`
200
202
  + 'background-color: black ; position: inherit }'
201
- + '.chatgpt-modal input[type="checkbox"]:focus { outline: none ; box-shadow: none }'
203
+ + '.chatgpt-modal input[type=checkbox]:focus { outline: none ; box-shadow: none }'
202
204
  );
203
205
  }
204
206
 
@@ -314,7 +316,7 @@ const chatgpt = {
314
316
  }, 500);
315
317
  }
316
318
 
317
- }, 135);
319
+ }, 155);
318
320
  };
319
321
 
320
322
  return modalContainer.id; // if assignment used
@@ -455,7 +457,7 @@ const chatgpt = {
455
457
  async isIdle(timeout = null) {
456
458
  const obsConfig = { childList: true, subtree: true },
457
459
  selectors = { msgDiv: 'div[data-message-author-role]',
458
- replyDiv: 'div[data-message-author-role="assistant"]' };
460
+ replyDiv: 'div[data-message-author-role=assistant]' };
459
461
 
460
462
  // Create promises
461
463
  const timeoutPromise = timeout ? new Promise(resolve => setTimeout(() => resolve(false), timeout)) : null;
@@ -620,7 +622,7 @@ const chatgpt = {
620
622
  filename = `${ parsedHtml.querySelector('title').textContent || 'ChatGPT conversation' }.html`;
621
623
 
622
624
  // Convert relative CSS paths to absolute ones
623
- const cssLinks = parsedHtml.querySelectorAll('link[rel="stylesheet"]');
625
+ const cssLinks = parsedHtml.querySelectorAll('link[rel=stylesheet]');
624
626
  cssLinks.forEach(link => {
625
627
  const href = link.getAttribute('href');
626
628
  if (href?.startsWith('/')) link.setAttribute('href', 'https://chat.openai.com' + href);
@@ -932,7 +934,7 @@ const chatgpt = {
932
934
  getLastResponse() { return chatgpt.getChatData('active', 'msg', 'chatgpt', 'latest'); },
933
935
 
934
936
  getNewChatButton() {
935
- return document.querySelector('button[data-testid*="new-chat-button"], button:has([d^="M15.6729"])'); },
937
+ return document.querySelector('button[data-testid*=new-chat-button], button:has([d^="M15.6729"])'); },
936
938
 
937
939
  getNewChatLink() { return document.querySelector('nav a[href="/"]'); },
938
940
  getRegenerateButton() { return document.querySelector('button:has([d^="M3.06957"])'); },
@@ -949,8 +951,8 @@ const chatgpt = {
949
951
  getResponseFromAPI(chatToGet, responseToGet) { return chatgpt.response.getFromAPI(chatToGet, responseToGet); },
950
952
  getResponseFromDOM(pos) { return chatgpt.response.getFromDOM(pos); },
951
953
  getScrollToBottomButton() { return document.querySelector('button:has([d^="M12 21C11.7348"])'); },
952
- getSendButton() { return document.querySelector('[data-testid="send-button"]'); },
953
- getStopButton() { return document.querySelector('button[data-testid="stop-button"]'); },
954
+ getSendButton() { return document.querySelector('[data-testid=send-button]'); },
955
+ getStopButton() { return document.querySelector('button[data-testid=stop-button]'); },
954
956
 
955
957
  getUserLanguage() {
956
958
  return navigator.languages[0] || navigator.language || navigator.browserLanguage ||
@@ -1211,7 +1213,7 @@ const chatgpt = {
1211
1213
  }
1212
1214
 
1213
1215
  const addElementsToMenu = () => {
1214
- const optionButtons = document.querySelectorAll('a[role="menuitem"]');
1216
+ const optionButtons = document.querySelectorAll('a[role=menuitem]');
1215
1217
  let cssClasses;
1216
1218
 
1217
1219
  for (const navLink of optionButtons)
@@ -1230,7 +1232,7 @@ const chatgpt = {
1230
1232
  };
1231
1233
 
1232
1234
  this.elements.push(newElement);
1233
- const menuBtn = document.querySelector('nav button[id*="headless"]');
1235
+ const menuBtn = document.querySelector('nav button[id*=headless]');
1234
1236
  if (!this.addedEvent) { // to prevent adding more than one event
1235
1237
  menuBtn?.addEventListener('click', () => { setTimeout(addElementsToMenu, 25); });
1236
1238
  this.addedEvent = true; }
@@ -1239,12 +1241,12 @@ const chatgpt = {
1239
1241
  },
1240
1242
 
1241
1243
  close() {
1242
- try { document.querySelector('nav [id*="menu-button"][aria-expanded="true"]').click(); }
1244
+ try { document.querySelector('nav [id*=menu-button][aria-expanded=true]').click(); }
1243
1245
  catch (err) { console.error(err.message); }
1244
1246
  },
1245
1247
 
1246
1248
  open() {
1247
- try { document.querySelector('nav [id*="menu-button"][aria-expanded="false"]').click(); }
1249
+ try { document.querySelector('nav [id*=menu-button][aria-expanded=false]').click(); }
1248
1250
  catch (err) { console.error(err.message); }
1249
1251
  }
1250
1252
  },
@@ -1285,7 +1287,7 @@ const chatgpt = {
1285
1287
  + (notificationDiv.isRight ? 'Right' : 'Left');
1286
1288
 
1287
1289
  // Create/append/update notification style (if missing or outdated)
1288
- const thisUpdated = 20231110; // datestamp of last edit for this file's `notifStyle`
1290
+ const thisUpdated = 1735475527153 // timestamp of last edit for this file's `notifStyle`
1289
1291
  let notifStyle = document.querySelector('#chatgpt-notif-style'); // try to select existing style
1290
1292
  if (!notifStyle || parseInt(notifStyle.getAttribute('last-updated'), 10) < thisUpdated) { // if missing or outdated
1291
1293
  if (!notifStyle) { // outright missing, create/id/attr/append it first
@@ -1295,6 +1297,8 @@ const chatgpt = {
1295
1297
  }
1296
1298
  notifStyle.innerText = ( // update prev/new style contents
1297
1299
  '.chatgpt-notif {'
1300
+ + 'font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC",'
1301
+ + '"Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", sans-serif ;'
1298
1302
  + '.no-mobile-tap-outline { outline: none ; -webkit-tap-highlight-color: transparent }'
1299
1303
  + 'background-color: black ; padding: 10px 13px 10px 18px ; border-radius: 11px ; border: 1px solid #f5f5f7 ;' // bubble style
1300
1304
  + 'opacity: 0 ; position: fixed ; z-index: 9999 ; font-size: 1.8rem ; color: white ;' // visibility
@@ -1518,7 +1522,7 @@ const chatgpt = {
1518
1522
  },
1519
1523
 
1520
1524
  getFromDOM(pos) {
1521
- const responseDivs = document.querySelectorAll('div[data-message-author-role="assistant"]'),
1525
+ const responseDivs = document.querySelectorAll('div[data-message-author-role=assistant]'),
1522
1526
  strPos = pos.toString().toLowerCase();
1523
1527
  let response = '';
1524
1528
  if (!responseDivs.length) return console.error('No conversation found!');
@@ -1825,7 +1829,7 @@ const chatgpt = {
1825
1829
  isOff() { return !this.isOn(); },
1826
1830
  isOn() {
1827
1831
  const sidebar = (() => {
1828
- return chatgpt.sidebar.exists() ? document.querySelector('[class*="sidebar"]') : null; })();
1832
+ return chatgpt.sidebar.exists() ? document.querySelector('[class*=sidebar]') : null; })();
1829
1833
  if (!sidebar) { console.error('Sidebar element not found!'); return false; }
1830
1834
  else return chatgpt.browser.isMobile() ?
1831
1835
  document.documentElement.style.overflow == 'hidden'
@@ -1833,7 +1837,7 @@ const chatgpt = {
1833
1837
  },
1834
1838
 
1835
1839
  toggle() {
1836
- const sidebarToggle = document.querySelector('button[data-testid*="sidebar-button"]');
1840
+ const sidebarToggle = document.querySelector('button[data-testid*=sidebar-button]');
1837
1841
  if (!sidebarToggle) console.error('Sidebar toggle not found!');
1838
1842
  sidebarToggle.click();
1839
1843
  },
@@ -1943,8 +1947,8 @@ const cjsBtnActions = ['click', 'get'], cjsTargetTypes = [ 'button', 'link', 'di
1943
1947
  for (const btnAction of cjsBtnActions) {
1944
1948
  chatgpt[btnAction + 'Button'] = function handleButton(buttonIdentifier) {
1945
1949
  const button = /^[.#]/.test(buttonIdentifier) ? document.querySelector(buttonIdentifier)
1946
- : /send/i.test(buttonIdentifier) ? document.querySelector('form button[class*="bottom"]')
1947
- : /scroll/i.test(buttonIdentifier) ? document.querySelector('button[class*="cursor"]')
1950
+ : /send/i.test(buttonIdentifier) ? document.querySelector('form button[class*=bottom]')
1951
+ : /scroll/i.test(buttonIdentifier) ? document.querySelector('button[class*=cursor]')
1948
1952
  : (function() { // get via text content
1949
1953
  for (const button of document.querySelectorAll('button')) { // try buttons
1950
1954
  if (button.textContent.toLowerCase().includes(buttonIdentifier.toLowerCase())) {
@@ -1,4 +1,10 @@
1
1
  window.dom = {
2
+
3
+ imports: {
4
+ import(deps) { // { env) }
5
+ for (const depName in deps) this[depName] = deps[depName] }
6
+ },
7
+
2
8
  create: {
3
9
  elem(elemType, attrs = {}) {
4
10
  const elem = document.createElement(elemType)
@@ -13,14 +19,15 @@ window.dom = {
13
19
  }
14
20
  },
15
21
 
16
- fillStarryBG(targetNode) { // requires https://assets.aiwebextensions.com/styles/css/<black|white>-rising-stars.min.css
22
+ fillStarryBG(targetNode) { // requires https://assets.aiwebextensions.com/styles/rising-stars/css/<black|white>.min.css
23
+ if (targetNode.querySelector('[id*=stars]')) return
17
24
  const starsDivsContainer = document.createElement('div')
18
25
  starsDivsContainer.style.cssText = 'position: absolute ; top: 0 ; left: 0 ;' // hug targetNode's top-left corner
19
26
  + 'height: 100% ; width: 100% ; border-radius: 15px ; overflow: clip ;' // bound innards exactly by targetNode
20
27
  + 'z-index: -1'; // allow interactive elems to be clicked
21
28
  ['sm', 'med', 'lg'].forEach(starSize => {
22
29
  const starsDiv = document.createElement('div')
23
- starsDiv.id = `${ chatgpt.isDarkMode() ? 'white' : 'black' }-stars-${starSize}`
30
+ starsDiv.id = `${ this.imports.env.ui.scheme == 'dark' ? 'white' : 'black' }-stars-${starSize}`
24
31
  starsDivsContainer.append(starsDiv)
25
32
  })
26
33
  targetNode.prepend(starsDivsContainer)
@@ -27,4 +27,4 @@ window.settings = {
27
27
  chrome.storage.sync.set({ [key]: val }) // save to Chrome extension storage
28
28
  window.config[key] = val // save to memory
29
29
  }
30
- }
30
+ };
@@ -3,7 +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": "2024.12.20",
6
+ "version": "2024.12.29",
7
7
  "author": "KudoAI",
8
8
  "homepage_url": "https://github.com/KudoAI/chatgpt.js-chrome-starter",
9
9
  "icons": {
@@ -18,10 +18,7 @@
18
18
  "matches": [ "<all_urls>" ],
19
19
  "resources": [ "components/modals.js", "lib/chatgpt.js", "lib/dom.js", "lib/settings.js" ]
20
20
  }],
21
- "content_scripts": [{
22
- "matches": [ "https://chatgpt.com/*" ],
23
- "js": [ "content.js" ]
24
- }],
21
+ "content_scripts": [{ "matches": [ "https://chatgpt.com/*" ], "js": [ "content.js" ] }],
25
22
  "background": { "service_worker": "service-worker.js" },
26
23
  "minimum_chrome_version": "88"
27
24
  }
@@ -10,7 +10,7 @@
10
10
 
11
11
  // Import APP data
12
12
  const { app } = await chrome.storage.sync.get('app')
13
- icons.dependencies.import({ app }) // for src's using app.urls.assetHost
13
+ icons.imports.import({ app }) // for src's using app.urls.assetHost
14
14
 
15
15
  // Define FUNCTIONS
16
16
 
@@ -55,7 +55,7 @@
55
55
 
56
56
  // Create CHILD menu entries on chatgpt.com
57
57
  if (env.site == 'chatgpt') {
58
- await settings.load(settings.availKeys)
58
+ await settings.load(Object.keys(settings.controls))
59
59
 
60
60
  // Create/insert child section
61
61
  const togglesDiv = dom.create.elem('div', { class: 'menu' })
@@ -65,9 +65,10 @@
65
65
  Object.keys(settings.controls).forEach(key => {
66
66
 
67
67
  // Init elems
68
- const menuItemDiv = dom.create.elem('div', { class: 'menu-item menu-area' }),
69
- menuLabel = dom.create.elem('label', { class: 'menu-icon' }),
70
- menuLabelSpan = document.createElement('span')
68
+ const menuItemDiv = dom.create.elem('div', {
69
+ class: 'menu-item menu-area', title: settings.controls[key].helptip || '' })
70
+ const menuLabel = dom.create.elem('label', { class: 'menu-icon' })
71
+ const menuLabelSpan = dom.create.elem('span')
71
72
  let menuInput, menuSlider
72
73
  menuLabelSpan.textContent = settings.controls[key].label
73
74
  if (settings.controls[key].type == 'toggle') {
@@ -92,7 +93,8 @@
92
93
  event.stopImmediatePropagation()
93
94
  menuInput.onchange = () => {
94
95
  settings.save(key, !config[key]) ; sync.configToUI({ updatedKey: key })
95
- notify(`${settings.controls[key].label} ${ /disabled|hidden/i.test(key) != config[key] ? 'ON' : 'OFF' }`)
96
+ notify(`${settings.controls[key].label} ${
97
+ /disabled|hidden/i.test(key) != config[key] ? 'ON' : 'OFF' }`)
96
98
  }
97
99
  } else if (settings.controls[key].type == 'prompt') {
98
100
  // custom logic for each prompt based on key name
@@ -103,16 +105,16 @@
103
105
  }
104
106
 
105
107
  // Create/append FOOTER container
106
- const footer = document.createElement('footer')
107
- document.body.append(footer)
108
+ const footer = dom.create.elem('footer') ; document.body.append(footer)
108
109
 
109
110
  // Create/append CHATGPT.JS footer logo
110
111
  const cjsDiv = dom.create.elem('div', { class: 'chatgpt-js' })
111
112
  const cjsLogo = dom.create.elem('img', {
112
113
  title: 'Powered by chatgpt.js',
113
- src: `${app.urls.cjsMediaHost}/images/badges/powered-by-chatgpt.js-faded.png?a439ab6` })
114
+ src: `${app.urls.cjsMediaHost}/images/badges/powered-by-chatgpt.js-faded.png?b2a1975` })
114
115
  cjsLogo.onmouseover = cjsLogo.onmouseout = event => cjsLogo.src = `${
115
- app.urls.cjsMediaHost}/images/badges/powered-by-chatgpt.js${ event.type == 'mouseover' ? '' : '-faded' }.png?a439ab6`
116
+ app.urls.cjsMediaHost}/images/badges/powered-by-chatgpt.js${
117
+ event.type == 'mouseover' ? '' : '-faded' }.png?b2a1975`
116
118
  cjsLogo.onclick = () => chrome.tabs.create({ url: app.urls.chatgptJS })
117
119
  cjsDiv.append(cjsLogo) ; footer.append(cjsDiv)
118
120
 
@@ -132,7 +134,7 @@
132
134
  moreExtensionsSpan.onclick = () => { chrome.tabs.create({ url: app.urls.relatedExtensions }) ; close() }
133
135
  moreExtensionsSpan.append(moreExtensionsIcon) ; footer.append(moreExtensionsSpan)
134
136
 
135
- // Hide loading spinner
136
- document.querySelectorAll('[class^="loading"]').forEach(elem => elem.style.display = 'none')
137
+ // Remove loading spinner
138
+ document.querySelectorAll('[class^=loading]').forEach(elem => elem.remove())
137
139
 
138
140
  })()
@@ -4,20 +4,35 @@ body { width: max-content ; margin: 0 ; overflow: clip }
4
4
 
5
5
  /* General font */
6
6
  body, button, input, select, textarea {
7
- font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", sans-serif ;
7
+ font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto,
8
+ "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", sans-serif ;
8
9
  font-size: .905rem ; user-select: none
9
10
  }
10
11
  a { color: #999 ; text-decoration: none }
11
12
  a:focus, a:hover { text-decoration: underline ; color: inherit }
12
13
 
13
- /* Loading elems */
14
- .loading-bg { background-color: white ; width: 100% ; height: 100% ; position: absolute ; z-index: 1111; }
14
+ /* Loader */
15
+ .loading-bg {
16
+ background-color: white ; width: 100% ; height: 100% ; position: absolute ; z-index: 1111 ;
17
+ display: inline-grid ; align-content: center ; justify-content: center /* center spinner */
18
+ }
15
19
  .loading-spinner {
16
- border: 8px solid #f3f3f3 ; border-top: 8px solid #3498db ; border-radius: 50% ;
17
- width: 15vh ; height: 15vh ; animation: spin 1s linear infinite ;
18
- position: absolute ; top: calc(50% - 7.5vh - 8px) ; left: calc(50% - 7.5vh)
20
+ width: 11px ; aspect-ratio: 1 ; border-radius: 50% ; border: 5px solid #000 ;
21
+ animation: loader-move-head-tail 0.8s infinite linear alternate, loader-rotate 1.6s infinite linear
22
+ }
23
+ @keyframes loader-move-head-tail {
24
+ 0% { clip-path: polygon(50% 50%, 0 0, 50% 0, 50% 0, 50% 0, 50% 0, 50% 0) }
25
+ 12.5% { clip-path: polygon(50% 50%, 0 0, 50% 0, 100% 0, 100% 0, 100% 0, 100% 0) }
26
+ 25% { clip-path: polygon(50% 50%, 0 0, 50% 0, 100% 0, 100% 100%, 100% 100%, 100% 100%) }
27
+ 50% { clip-path: polygon(50% 50%, 0 0, 50% 0, 100% 0, 100% 100%, 50% 100%, 0 100%) }
28
+ 62.5% { clip-path: polygon(50% 50%, 100% 0, 100% 0%, 100% 0, 100% 100%, 50% 100%, 0 100%) }
29
+ 75% { clip-path: polygon(50% 50%, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 50% 100%, 0 100%) }
30
+ 100% { clip-path: polygon(50% 50%, 50% 100%, 50% 100%, 50% 100%, 50% 100%, 50% 100%, 0 100%) }
19
31
  }
20
- @keyframes spin { 0% { transform: rotate(0deg) } 100% { transform: rotate(360deg) }}
32
+ @keyframes loader-rotate {
33
+ 0% { transform: scaleY(1) rotate(0deg) } 49.99% { transform: scaleY(1) rotate(135deg) }
34
+ 50% { transform: scaleY(-1) rotate(0deg) } 100% { transform: scaleY(-1) rotate(-135deg) }
35
+ }
21
36
 
22
37
  /* Header */
23
38
  .menu-header {
@@ -36,8 +51,7 @@ a:focus, a:hover { text-decoration: underline ; color: inherit }
36
51
  .menu-icon { padding: 8px }
37
52
  .menu-area:focus, .menu-area:hover { /* add hover color/cursor */
38
53
  color: var(--bg) ; background: rgb(100, 149, 237) ; cursor: pointer }
39
- .menu-item:hover .toggle-switch .slider, .menu-item:hover span { filter: invert(1) } /* invert toggle switch + label */
40
- .menu-item:hover .menu-icon { filter: none } /* ...but not non-toggle icons */
54
+ .menu-item:hover span:not(.slider) { filter: invert(1) } /* invert setting labels on hover */
41
55
  .menu-item > label > .slider { transform: scale(0.95) ; top: 1px } /* make child toggles smaller */
42
56
  .menu-prompt { margin-left: 2px } /* align non-toggle items */
43
57
 
@@ -52,7 +66,7 @@ a:focus, a:hover { text-decoration: underline ; color: inherit }
52
66
  border: 1px solid black ; border-radius: 50% ; background-color: white ; content: ""
53
67
  }
54
68
  .toggle-switch input[type="checkbox"]:checked + .slider { background-color: black } /* color active slider */
55
- .toggle-switch input[type="checkbox"]:checked + .slider::before { transform: translateX(9px) } /* move knob right when toggled */
69
+ .toggle-switch input[type="checkbox"]:checked + .slider::before { transform: translateX(9px) } /* toggle knob right */
56
70
 
57
71
  /* Footer */
58
72
  footer { font-size: 12px ; text-align: center ; color: #999 ; background: #f5f5f5 ; height: 40px ; line-height: 40px }
@@ -1,9 +1,12 @@
1
1
  // Init APP data
2
2
  const app = {
3
- symbol: '🤖', version: chrome.runtime.getManifest().version,
3
+ version: chrome.runtime.getManifest().version, symbol: '🤖', cssPrefix: 'chatgpt-extension',
4
+ author: { name: 'KudoAI', url: 'https://kudoai.com' },
4
5
  urls: {
5
6
  assetHost: 'https://cdn.jsdelivr.net/gh/KudoAI/chatgpt.js-chrome-starter',
7
+ chatgptJS: 'https://chatgptjs.org',
6
8
  cjsMediaHost: 'https://media.chatgptjs.org',
9
+ contributors: 'https://docs.chatgptjs.org/#-contributors',
7
10
  gitHub: 'https://github.com/KudoAI/chatgpt.js-chrome-starter',
8
11
  relatedExtensions: 'https://aiwebextensions.com',
9
12
  support: 'https://github.com/KudoAI/chatgpt.js-chrome-starter/issues'
@@ -11,13 +14,13 @@ const app = {
11
14
  }
12
15
  chrome.storage.sync.set({ app }) // save to Chrome storage
13
16
 
14
- // Launch ChatGPT on install
17
+ // Launch CHATGPT on install
15
18
  chrome.runtime.onInstalled.addListener(details => {
16
19
  if (details.reason == 'install')
17
20
  chrome.tabs.create({ url: 'https://chatgpt.com/' })
18
21
  })
19
22
 
20
- // Sync settings to activated tabs
23
+ // Sync SETTINGS to activated tabs
21
24
  chrome.tabs.onActivated.addListener(activeInfo =>
22
25
  chrome.tabs.sendMessage(activeInfo.tabId, { action: 'syncConfigToUI' }))
23
26
 
@@ -3,13 +3,13 @@
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 2024.12.20
6
+ // @version 2024.12.29
7
7
  // @license MIT
8
- // @icon https://cdn.jsdelivr.net/gh/KudoAI/chatgpt.js@3.4.0/starters/greasemonkey/media/images/icons/robot/icon48.png
9
- // @icon64 https://cdn.jsdelivr.net/gh/KudoAI/chatgpt.js@3.4.0/starters/greasemonkey/media/images/icons/robot/icon64.png
8
+ // @icon https://cdn.jsdelivr.net/gh/KudoAI/chatgpt.js@3.5.0/starters/greasemonkey/media/images/icons/robot/icon48.png
9
+ // @icon64 https://cdn.jsdelivr.net/gh/KudoAI/chatgpt.js@3.5.0/starters/greasemonkey/media/images/icons/robot/icon64.png
10
10
  // @match *://chatgpt.com/*
11
11
  // @match *://chat.openai.com/*
12
- // @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.4.0/dist/chatgpt.min.js
12
+ // @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.5.0/dist/chatgpt.min.js
13
13
  // @grant GM_getValue
14
14
  // @grant GM_setValue
15
15
  // @noframes