c.ai X Text Color

Lets you change the text colors as you wish and highlight chosen words

目前为 2024-08-30 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name c.ai X Text Color
  3. // @namespace c.ai X Text Color
  4. // @match https://character.ai/*
  5. // @grant none
  6. // @license MIT
  7. // @version 3.1
  8. // @author Vishanka via chatGPT
  9. // @description Lets you change the text colors as you wish and highlight chosen words
  10. // @icon https://i.imgur.com/ynjBqKW.png
  11. // ==/UserScript==
  12.  
  13.  
  14. (function () {
  15.  
  16. const currentTheme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
  17. var plaintextColor = localStorage.getItem('plaintext_color');
  18. var italicColor = localStorage.getItem('italic_color');
  19. var charbubbleColor = localStorage.getItem('charbubble_color') || '#26272B';
  20. var userbubbleColor = localStorage.getItem('userbubble_color') || '#303136';
  21. // Default color if 'plaintext_color' is not set
  22. var defaultColor = '#A2A2AC';
  23. var GuideColor = localStorage.getItem('guide_color') || '#131316';
  24. var BodyColor = localStorage.getItem('body_color') || '#18181B';
  25. var InputColor = localStorage.getItem('input_color') || '#202024';
  26. var AccentColor = localStorage.getItem('accent_color') || '#26272b';
  27.  
  28. // Use the retrieved color or default color
  29. var color = plaintextColor || defaultColor;
  30.  
  31. // Create the CSS style
  32. var css = "p[node='[object Object]'] { color: " + color + " !important; font-family: '__Inter_918210','Noto Sans', sans-serif !important; } p, textarea, button, div.text-sm { font-family: '__Inter_918210','Noto Sans', sans-serif !important; } em { color: " + italicColor + " !important; }";
  33.  
  34. css += `.mt-1.bg-surface-elevation-2 { background-color: ${charbubbleColor}; } .mt-1.bg-surface-elevation-3 { background-color: ${userbubbleColor}; }`;
  35.  
  36.  
  37.  
  38. var head = document.getElementsByTagName("head")[0];
  39. var style = document.createElement("style");
  40. style.setAttribute("type", "text/css");
  41. style.innerHTML = css;
  42. head.appendChild(style);
  43.  
  44.  
  45. // Function to update CSS variables
  46. function updateCSSVariable(variableName, value) {
  47. document.documentElement.style.setProperty(variableName, value);
  48. }
  49.  
  50. if (currentTheme === 'dark') {
  51. // Update the specific CSS variables
  52. updateCSSVariable('--G800', AccentColor);
  53. updateCSSVariable('--G850', InputColor);
  54. updateCSSVariable('--G900', BodyColor);
  55. updateCSSVariable('--G950', GuideColor);
  56.  
  57.  
  58. updateCSSVariable('--G50', '#fafafa');
  59. updateCSSVariable('--G100', '#f4f4f5');
  60. updateCSSVariable('--G150', '#ececee');
  61. }
  62. else {
  63. // Update CSS variables for light theme (or any other theme)
  64. updateCSSVariable('--G850', '#202024');
  65. updateCSSVariable('--G900', '#18181B');
  66. updateCSSVariable('--G950', '#131316');
  67. updateCSSVariable('--G50', InputColor);
  68. updateCSSVariable('--G100', BodyColor);
  69. updateCSSVariable('--G150', GuideColor);
  70. }
  71. })();
  72.  
  73.  
  74.  
  75.  
  76. function changeColors() {
  77. const pTags = document.getElementsByTagName("p");
  78. const quotationMarksColor = localStorage.getItem('quotationmarks_color') || '#FFFFFF';
  79. const customColor = localStorage.getItem('custom_color') || '#FFFFFF';
  80. const wordlistCc = JSON.parse(localStorage.getItem('wordlist_cc')) || [];
  81.  
  82. const wordRegex = wordlistCc.length > 0 ? new RegExp('\\b(' + wordlistCc.map(word => word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('|') + ')\\b', 'gi') : null;
  83.  
  84. Array.from(pTags).forEach((pTag) => {
  85. if (
  86. pTag.dataset.colorChanged === "true" ||
  87. pTag.querySelector("code") ||
  88. pTag.querySelector("img") ||
  89. pTag.querySelector("textarea") ||
  90. pTag.querySelector("button") ||
  91. pTag.querySelector("div")
  92. ) {
  93. return; // Skip iteration
  94. }
  95.  
  96. let text = pTag.innerHTML;
  97.  
  98. // Save .katex elements' original HTML and replace with placeholders
  99. const katexElems = Array.from(pTag.querySelectorAll(".katex"));
  100. const katexReplacements = katexElems.map((elem, index) => {
  101. const placeholder = `KATEX_PLACEHOLDER_${index}`;
  102. text = text.replace(elem.outerHTML, placeholder);
  103. return { html: elem.outerHTML, placeholder };
  104. });
  105.  
  106. // Handle <a> tags by removing them temporarily and saving their HTML for later restoration
  107. const aTags = Array.from(pTag.getElementsByTagName("a"));
  108. const aTagsReplacements = aTags.map((aTag, j) => {
  109. const placeholder = `REPLACE_ME_${j}`;
  110. text = text.replace(aTag.outerHTML, placeholder);
  111. return { tag: aTag, placeholder };
  112. });
  113.  
  114. // Change text within quotation marks and for specific words based on the regex
  115. text = text.replace(/(["“”«»].*?["“”«»])/g, `<span style="color: ${quotationMarksColor}">$1</span>`);
  116. // text = text.replace(/(["“”«»][^"]*?,["“”«»])/g, `<span style="color: #E0DF7F">$1</span>`);
  117.  
  118. if (wordRegex) {
  119. text = text.replace(wordRegex, `<span style="color: ${customColor}">$1</span>`);
  120. }
  121.  
  122. // Restore .katex elements and <a> tags
  123. [...katexReplacements, ...aTagsReplacements].forEach(({ html, placeholder, tag }) => {
  124. text = text.replace(placeholder, html || tag.outerHTML);
  125. });
  126.  
  127. // Update the innerHTML and mark the <p> tag to avoid re-processing
  128. pTag.innerHTML = text;
  129. pTag.dataset.colorChanged = "true";
  130. });
  131.  
  132. console.log("Changed colors");
  133. }
  134.  
  135. const divElements = document.querySelectorAll('div');
  136.  
  137. divElements.forEach(div => {
  138. const observer = new MutationObserver(changeColors);
  139. observer.observe(div, { subtree: true, childList: true });
  140. });
  141.  
  142.  
  143.  
  144. function createButton(symbol, onClick) {
  145. const colorpalettebutton = document.createElement('button');
  146. colorpalettebutton.innerHTML = symbol;
  147. colorpalettebutton.style.position = 'relative';
  148. colorpalettebutton.style.background = 'none';
  149. colorpalettebutton.style.border = 'none';
  150. colorpalettebutton.style.fontSize = '18px';
  151. colorpalettebutton.style.top = '-5px';
  152. colorpalettebutton.style.cursor = 'pointer';
  153. colorpalettebutton.addEventListener('click', onClick);
  154. return colorpalettebutton;
  155. }
  156.  
  157. // Function to create the color selector panel
  158. function createColorPanel() {
  159. const panel = document.createElement('div');
  160. panel.id = 'colorPanel';
  161. panel.style.position = 'fixed';
  162. panel.style.top = '50%';
  163. panel.style.left = '50%';
  164. panel.style.transform = 'translate(-50%, -50%)';
  165. const currentTheme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
  166. if (currentTheme === 'dark') {
  167. panel.style.backgroundColor = 'rgba(19, 19, 22, 0.95)';
  168. } else {
  169. panel.style.backgroundColor = 'rgba(214, 214, 221, 0.95)';
  170. }
  171. panel.style.border = 'none';
  172. panel.style.borderRadius = '5px';
  173. panel.style.padding = '20px';
  174. // panel.style.border = '2px solid #000';
  175. panel.style.zIndex = '9999';
  176.  
  177. const categories = ['italic', 'quotationmarks', 'plaintext', 'custom', 'charbubble', 'userbubble', 'guide', 'body', 'input', 'accent'];
  178.  
  179. const colorPickers = {};
  180.  
  181. // Set a fixed width for the labels
  182. const labelWidth = '150px';
  183.  
  184.  
  185.  
  186.  
  187. categories.forEach(category => {
  188. const colorPicker = document.createElement('input');
  189. colorPicker.type = 'color';
  190.  
  191. // Retrieve stored color from local storage
  192. const storedColor = localStorage.getItem(`${category}_color`);
  193. if (storedColor) {
  194. colorPicker.value = storedColor;
  195. }
  196.  
  197. colorPickers[category] = colorPicker;
  198.  
  199. // Create a div to hold color picker
  200. const colorDiv = document.createElement('div');
  201. colorDiv.style.position = 'relative';
  202. colorDiv.style.width = '20px';
  203. colorDiv.style.height = '20px';
  204. colorDiv.style.marginLeft = '10px';
  205. colorDiv.style.top = '0px';
  206. colorDiv.style.backgroundColor = colorPicker.value;
  207. colorDiv.style.display = 'inline-block';
  208. colorDiv.style.marginRight = '10px';
  209. colorDiv.style.cursor = 'pointer';
  210. colorDiv.style.border = '1px solid black';
  211.  
  212. // Event listener to open color picker when the color square is clicked
  213. colorDiv.addEventListener('click', function () {
  214. colorPicker.click();
  215. });
  216.  
  217. // Event listener to update the color div when the color changes
  218. colorPicker.addEventListener('input', function () {
  219. colorDiv.style.backgroundColor = colorPicker.value;
  220. });
  221.  
  222. const label = document.createElement('label');
  223. label.style.width = labelWidth; // Set fixed width for the label
  224. label.style.margin = '0'; // Reduce label margin
  225. label.style.padding = '0'; // Reduce label padding
  226. label.appendChild(document.createTextNode(`${category}: `));
  227.  
  228. // Reset button for each color picker
  229. const resetButton = createButton('↺', function () {
  230. colorPicker.value = getDefaultColor(category);
  231. colorDiv.style.backgroundColor = colorPicker.value;
  232. });
  233. resetButton.style.position = 'relative';
  234. resetButton.style.top = '-2px';
  235. resetButton.style.margin = '0'; // Reduce button margin
  236. resetButton.style.padding = '0'; // Reduce button padding
  237.  
  238. // Create a div to hold label, color picker, and reset button
  239. const containerDiv = document.createElement('div');
  240. containerDiv.style.margin = '2px 0'; // Reduce vertical margin between rows
  241. containerDiv.style.padding = '0'; // Reduce padding within each row
  242. containerDiv.style.display = 'flex'; // Flex display for better control over spacing
  243. containerDiv.style.alignItems = 'center'; // Center align items vertically
  244.  
  245. containerDiv.appendChild(label);
  246. containerDiv.appendChild(colorDiv);
  247. containerDiv.appendChild(resetButton);
  248.  
  249. panel.appendChild(containerDiv);
  250. });
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259. // Custom word list input
  260. const wordListInput = document.createElement('input');
  261. wordListInput.type = 'text';
  262. wordListInput.placeholder = 'Separate words with commas';
  263. wordListInput.style.width = '250px';
  264. wordListInput.style.height = '35px';
  265. wordListInput.style.borderRadius = '3px';
  266. wordListInput.style.marginBottom = '10px';
  267. panel.appendChild(wordListInput);
  268. panel.appendChild(document.createElement('br'));
  269.  
  270. const wordListContainer = document.createElement('div');
  271. wordListContainer.style.display = 'flex';
  272. wordListContainer.style.flexWrap = 'wrap';
  273. wordListContainer.style.maxWidth = '300px'; // Set a fixed maximum width for the container
  274.  
  275. // Display custom word list buttons
  276. const wordListArray = JSON.parse(localStorage.getItem('wordlist_cc')) || [];
  277. const wordListButtons = [];
  278.  
  279. function createWordButton(word) {
  280. const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
  281.  
  282. const removeSymbol = isMobile ? '×' : '🞮';
  283.  
  284. const wordButton = createButton(`${word} ${removeSymbol}`, function() {
  285. // Remove the word from the list and update the panel
  286. const index = wordListArray.indexOf(word);
  287. if (index !== -1) {
  288. wordListArray.splice(index, 1);
  289. updateWordListButtons();
  290. }
  291. });
  292.  
  293. // Word Buttons
  294. wordButton.style.borderRadius = '3px';
  295. wordButton.style.border = 'none';
  296. if (currentTheme === 'dark') {
  297. wordButton.style.backgroundColor = '#26272B';
  298. } else {
  299. wordButton.style.backgroundColor = '#E4E4E7';
  300. }
  301. wordButton.style.marginBottom = '5px';
  302. wordButton.style.marginRight = '5px';
  303. wordButton.style.fontSize = '16px';
  304. wordButton.classList.add('word-button');
  305. return wordButton;
  306. }
  307.  
  308. function updateWordListButtons() {
  309. wordListContainer.innerHTML = ''; // Clear the container
  310. wordListArray.forEach(word => {
  311. const wordButton = createWordButton(word);
  312. wordListContainer.appendChild(wordButton);
  313. });
  314. }
  315.  
  316. // Append wordListContainer to the panel
  317.  
  318.  
  319.  
  320. updateWordListButtons();
  321.  
  322. // Add Words button
  323. const addWordsButton = document.createElement('button');
  324. addWordsButton.textContent = 'Add';
  325. addWordsButton.style.marginTop = '-8px';
  326. addWordsButton.style.marginLeft = '5px';
  327. addWordsButton.style.borderRadius = '3px';
  328. addWordsButton.style.border = 'none';
  329. if (currentTheme === 'dark') {
  330. addWordsButton.style.backgroundColor = '#26272B';
  331. } else {
  332. addWordsButton.style.backgroundColor = '#E4E4E7';
  333. }
  334. addWordsButton.addEventListener('click', function() {
  335. // Get the input value, split into words, and add to wordListArray
  336. const wordListValue = wordListInput.value;
  337. const newWords = wordListValue.split(',').map(word => word.trim().toLowerCase()).filter(word => word !== ''); // Convert to lowercase and remove empty entries
  338. wordListArray.push(...newWords);
  339.  
  340. // Update the word list buttons in the panel
  341. updateWordListButtons();
  342. });
  343.  
  344. // Create a div to group the input and button on the same line
  345. const inputButtonContainer = document.createElement('div');
  346. inputButtonContainer.style.display = 'flex';
  347. inputButtonContainer.style.alignItems = 'center';
  348.  
  349. inputButtonContainer.appendChild(wordListInput);
  350. inputButtonContainer.appendChild(addWordsButton);
  351.  
  352. // Append the container to the panel
  353. panel.appendChild(inputButtonContainer);
  354. panel.appendChild(wordListContainer);
  355. // Create initial word list buttons
  356. updateWordListButtons();
  357.  
  358.  
  359. // OK button
  360. const okButton = document.createElement('button');
  361. okButton.textContent = 'Confirm';
  362. okButton.style.marginTop = '-20px';
  363. okButton.style.width = '75px';
  364. okButton.style.height = '35px';
  365. okButton.style.marginRight = '5px';
  366. okButton.style.borderRadius = '3px';
  367. okButton.style.border = 'none';
  368. if (currentTheme === 'dark') {
  369. okButton.style.backgroundColor = '#26272B';
  370. } else {
  371. okButton.style.backgroundColor = '#D9D9DF';
  372. }
  373.  
  374. okButton.style.position = 'relative';
  375. okButton.style.left = '24%';
  376. //okButton.style.transform = 'translateX(-50%)';
  377. okButton.addEventListener('click', function() {
  378. // Save selected colors to local storage
  379. categories.forEach(category => {
  380. const oldValue = localStorage.getItem(`${category}_color`);
  381. const newValue = colorPickers[category].value;
  382.  
  383. if (oldValue !== newValue) {
  384. localStorage.setItem(`${category}_color`, newValue);
  385.  
  386. // If 'plaintext' color is changed, auto-reload the page
  387. if (category === 'plaintext' || category === 'guide' || category === 'body' || category === 'input') {
  388. window.location.reload();
  389. }
  390. }
  391. });
  392.  
  393.  
  394. // Save custom word list to local storage
  395. const wordListValue = wordListInput.value;
  396. const newWords = wordListValue.split(',').map(word => word.trim().toLowerCase()).filter(word => word !== ''); // Convert to lowercase and remove empty entries
  397. const uniqueNewWords = Array.from(new Set(newWords)); // Remove duplicates
  398.  
  399. // Check for existing words and add only new ones
  400. uniqueNewWords.forEach(newWord => {
  401. if (!wordListArray.includes(newWord)) {
  402. wordListArray.push(newWord);
  403. }
  404. });
  405.  
  406. localStorage.setItem('wordlist_cc', JSON.stringify(wordListArray));
  407.  
  408. updateWordListButtons();
  409.  
  410. // Close the panel
  411. panel.remove();
  412. });
  413.  
  414. // Cancel button
  415. const cancelButton = document.createElement('button');
  416. cancelButton.textContent = 'Cancel';
  417. cancelButton.style.marginTop = '-20px';
  418. cancelButton.style.borderRadius = '3px';
  419. cancelButton.style.width = '75px';
  420. cancelButton.style.marginLeft = '5px';
  421. cancelButton.style.height = '35px';
  422. cancelButton.style.border = 'none';
  423. if (currentTheme === 'dark') {
  424. cancelButton.style.backgroundColor = '#5E5E5E';
  425. } else {
  426. cancelButton.style.backgroundColor = '#CBD2D4';
  427. }
  428. cancelButton.style.position = 'relative';
  429. cancelButton.style.left = '25%';
  430. cancelButton.addEventListener('click', function() {
  431. // Close the panel without saving
  432. panel.remove();
  433. });
  434.  
  435. // ==== PRESETS ========
  436. // Create button
  437. const preset1 = document.createElement('button');
  438. preset1.style.marginBottom = '20px';
  439. preset1.style.borderRadius = '3px';
  440. preset1.style.width = '30px';
  441. preset1.style.marginLeft = '5px';
  442. preset1.style.height = '30px';
  443. preset1.style.border = 'none';
  444.  
  445. // Set image as button background
  446. preset1.style.backgroundImage = "url('https://i.imgur.com/91Z4AwP.png')";
  447. preset1.style.backgroundSize = 'contain';
  448. preset1.style.backgroundRepeat = 'no-repeat';
  449. preset1.style.backgroundPosition = 'center';
  450.  
  451.  
  452.  
  453.  
  454. // Event listener for button click
  455. preset1.addEventListener('click', function () {
  456.  
  457. // Show confirmation dialog
  458. const userConfirmed = confirm('All colors will be replaced with Discord pallet. Proceed?');
  459.  
  460.  
  461.  
  462. if (userConfirmed) {
  463.  
  464. function updateCSSVariable(variableName, value) {
  465. document.documentElement.style.setProperty(variableName, value);
  466. }
  467. updateCSSVariable('--G850', '#383A40'); //input
  468. updateCSSVariable('--G900', '#313338'); //body
  469. updateCSSVariable('--G950', '#232428'); //guide
  470. // Hardcode the selected colors to local storage
  471. const hardcodedColors = {
  472. 'guide': '#232428',
  473. 'input': '#383A40',
  474. 'body': '#313338',
  475. 'charbubble': '#383A40',
  476. 'userbubble': '#41434A',
  477. 'accent': '#3E4047'
  478. };
  479.  
  480. // Save hardcoded values to local storage
  481. Object.keys(hardcodedColors).forEach(category => {
  482. const newValue = hardcodedColors[category];
  483. localStorage.setItem(`${category}_color`, newValue);
  484. });
  485. window.location.reload();
  486. }
  487. });
  488.  
  489. const preset2 = document.createElement('button');
  490. preset2.style.marginBottom = '20px';
  491. preset2.style.borderRadius = '3px';
  492. preset2.style.width = '30px';
  493. preset2.style.marginLeft = '5px';
  494. preset2.style.height = '30px';
  495. preset2.style.border = 'none';
  496.  
  497. // Set image as button background
  498. preset2.style.backgroundImage = "url('https://i.imgur.com/PSkZ4Yq.png')";
  499. preset2.style.backgroundSize = 'contain';
  500. preset2.style.backgroundRepeat = 'no-repeat';
  501. preset2.style.backgroundPosition = 'center';
  502.  
  503.  
  504.  
  505.  
  506. // Event listener for button click
  507. preset2.addEventListener('click', function () {
  508.  
  509. // Show confirmation dialog
  510. const userConfirmed = confirm('All colors will be replaced with ChatGPT pallet. Proceed?');
  511.  
  512.  
  513.  
  514. if (userConfirmed) {
  515.  
  516. function updateCSSVariable(variableName, value) {
  517. document.documentElement.style.setProperty(variableName, value);
  518. }
  519. updateCSSVariable('--G850', '#2F2F2F'); //input
  520. updateCSSVariable('--G900', '#212121'); //body
  521. updateCSSVariable('--G950', '#171717'); //guide
  522. // Hardcode the selected colors to local storage
  523. const hardcodedColors = {
  524. 'guide': '#171717',
  525. 'input': '#2F2F2F',
  526. 'body': '#212121',
  527. 'charbubble': '#212121',
  528. 'userbubble': '#2F2F2F',
  529. 'accent': '#323232'
  530. };
  531.  
  532. // Save hardcoded values to local storage
  533. Object.keys(hardcodedColors).forEach(category => {
  534. const newValue = hardcodedColors[category];
  535. localStorage.setItem(`${category}_color`, newValue);
  536. });
  537. window.location.reload();
  538. }
  539. });
  540.  
  541. const preset3 = document.createElement('button');
  542. preset3.style.marginBottom = '20px';
  543. preset3.style.borderRadius = '3px';
  544. preset3.style.width = '30px';
  545. preset3.style.marginLeft = '5px';
  546. preset3.style.height = '30px';
  547. preset3.style.border = 'none';
  548.  
  549. // Set image as button background
  550. preset3.style.backgroundImage = "url('https://i.imgur.com/wWpHDIj.png')";
  551. preset3.style.backgroundSize = 'contain';
  552. preset3.style.backgroundRepeat = 'no-repeat';
  553. preset3.style.backgroundPosition = 'center';
  554.  
  555.  
  556.  
  557.  
  558. // Event listener for button click
  559. preset3.addEventListener('click', function () {
  560.  
  561. // Show confirmation dialog
  562. const userConfirmed = confirm('All colors will be replaced with old.character.ai pallet. Proceed?');
  563.  
  564.  
  565.  
  566. if (userConfirmed) {
  567.  
  568. function updateCSSVariable(variableName, value) {
  569. document.documentElement.style.setProperty(variableName, value);
  570. }
  571. updateCSSVariable('--G850', '#242525'); //input
  572. updateCSSVariable('--G900', '#242525'); //body
  573. updateCSSVariable('--G950', '#2B2C2D'); //guide
  574. // Hardcode the selected colors to local storage
  575. const hardcodedColors = {
  576. 'guide': '#2B2C2D',
  577. 'input': '#242525',
  578. 'body': '#242525',
  579. 'charbubble': '#242525',
  580. 'userbubble': '#2B2C2D',
  581. 'accent': '#363838'
  582. };
  583.  
  584. // Save hardcoded values to local storage
  585. Object.keys(hardcodedColors).forEach(category => {
  586. const newValue = hardcodedColors[category];
  587. localStorage.setItem(`${category}_color`, newValue);
  588. });
  589. window.location.reload();
  590. }
  591. });
  592.  
  593.  
  594.  
  595. panel.appendChild(preset1);
  596. panel.appendChild(preset2);
  597. panel.appendChild(preset3);
  598. panel.appendChild(document.createElement('br'));
  599. panel.appendChild(okButton);
  600. panel.appendChild(cancelButton);
  601.  
  602. document.body.appendChild(panel);
  603. }
  604.  
  605.  
  606.  
  607. // Function to get the default color for a category
  608. function getDefaultColor(category) {
  609. const currentTheme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
  610. if (currentTheme === 'dark') {
  611. const defaultColors = {
  612. 'italic': '#E0DF7F',
  613. 'quotationmarks': '#FFFFFF',
  614. 'plaintext': '#A2A2AC',
  615. 'custom': '#E0DF7F',
  616. 'charbubble': '#26272B',
  617. 'userbubble': '#303136',
  618. 'guide': '#131316',
  619. 'input': '#202024',
  620. 'body': '#18181B',
  621. 'accent': '#26272B'
  622. };
  623. return defaultColors[category];
  624. }
  625. else {
  626. const defaultColors = {
  627. 'italic': '#4F7AA6',
  628. 'quotationmarks': '#000000',
  629. 'plaintext': '#374151',
  630. 'custom': '#4F7AA6',
  631. 'charbubble': '#E4E4E7',
  632. 'userbubble': '#D9D9DF',
  633. 'guide': '#FAFAFA',
  634. 'input': '#F4F4F5',
  635. 'body': '#ECECEE',
  636. 'accent': '#26272B'
  637. };
  638. return defaultColors[category];
  639. }
  640. }
  641.  
  642.  
  643.  
  644. const mainButton = createButton('', function() {
  645. const colorPanelExists = document.getElementById('colorPanel');
  646. if (!colorPanelExists) {
  647. createColorPanel();
  648. }
  649. });
  650.  
  651. // Set the background image of the button to the provided image
  652. mainButton.style.backgroundImage = "url('https://i.imgur.com/yBgJ3za.png')";
  653. mainButton.style.backgroundSize = "cover";
  654. mainButton.style.position = "fixed"; // Use "fixed" for a position relative to the viewport
  655. mainButton.style.top = "10px"; // Adjust the top position as needed
  656. mainButton.style.right = "10px"; // Adjust the right position as needed
  657. mainButton.style.width = "22px"; // Adjust the width and height as needed
  658. mainButton.style.height = "22px"; // Adjust the width and height as needed
  659.  
  660. // Function to insert the mainButton into the body of the document
  661. function insertMainButton() {
  662. document.body.appendChild(mainButton);
  663. }
  664.  
  665. // Call the function to insert the mainButton into the body
  666. insertMainButton();
  667.  
  668. console.info('c.ai Text Color Button appended to the top right corner.');