您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Advanced text highlighting and note-taking for Character.ai with single-click and un-highlighting.
当前为
- // ==UserScript==
- // @name Character.ai Text Highlighter and Note Taker
- // @namespace http://tampermonkey.net/
- // @version 1.5
- // @description Advanced text highlighting and note-taking for Character.ai with single-click and un-highlighting.
- // @match https://character.ai/*
- // @grant GM_setValue
- // @grant GM_getValue
- // ==/UserScript==
- (function() {
- 'use strict';
- // Enhanced styling for highlights and notes
- const styleElement = document.createElement('style');
- styleElement.textContent = `
- .ca-highlight {
- background-color: yellow;
- color: black;
- cursor: pointer;
- transition: background-color 0.2s ease;
- display: inline; /* Ensure inline display for proper spacing */
- white-space: pre-wrap; /* Preserve whitespace */
- }
- .ca-highlight:hover {
- background-color: #ffff99;
- }
- .ca-note-popup {
- position: fixed;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- background-color: #1a1a1a;
- border: 2px solid #333;
- border-radius: 8px;
- padding: 20px;
- width: 350px;
- z-index: 10000;
- box-shadow: 0 4px 6px rgba(0,0,0,0.5);
- }
- .ca-note-input {
- width: 100%;
- margin-bottom: 10px;
- padding: 8px;
- background-color: #2a2a2a;
- color: white;
- border: 1px solid #444;
- border-radius: 4px;
- resize: vertical;
- min-height: 100px;
- }
- .ca-note-buttons {
- display: flex;
- justify-content: space-between;
- }
- .ca-note-save {
- background-color: #4CAF50;
- color: white;
- border: none;
- padding: 10px 15px;
- border-radius: 4px;
- cursor: pointer;
- margin-right: 10px;
- }
- .ca-note-cancel {
- background-color: #f44336;
- color: white;
- border: none;
- padding: 10px 15px;
- border-radius: 4px;
- cursor: pointer;
- }
- .ca-highlight-mode-indicator {
- position: fixed;
- top: 10px;
- right: 10px;
- background-color: yellow;
- color: black;
- padding: 5px 10px;
- border-radius: 4px;
- z-index: 9999;
- display: none;
- font-weight: bold;
- box-shadow: 0 2px 4px rgba(0,0,0,0.2);
- }
- .ca-note-button, .ca-unhighlight-button {
- margin-right: 10px;
- background-color: #555;
- color: white;
- border: none;
- padding: 8px 12px;
- border-radius: 4px;
- cursor: pointer;
- }
- .ca-unhighlight-button {
- background-color: #ff9800;
- }
- .ca-popup-menu {
- position: absolute;
- background-color: #1a1a1a;
- border: 1px solid #333;
- border-radius: 4px;
- padding: 5px;
- z-index: 10001;
- box-shadow: 0 2px 4px rgba(0,0,0,0.3);
- }
- `;
- document.head.appendChild(styleElement);
- // Create highlight mode indicator
- const highlightModeIndicator = document.createElement('div');
- highlightModeIndicator.classList.add('ca-highlight-mode-indicator');
- highlightModeIndicator.textContent = 'Highlight Mode';
- document.body.appendChild(highlightModeIndicator);
- // State variables
- let isHighlightMode = false;
- const STORAGE_KEY = 'caNotes';
- // Utility function to get unique identifier for a word
- function getWordIdentifier(word) {
- return `highlight_${btoa(word.trim())}`;
- }
- // Save note for a word
- function saveNote(word, note) {
- const identifier = getWordIdentifier(word);
- const savedNotes = JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}');
- savedNotes[identifier] = note;
- localStorage.setItem(STORAGE_KEY, JSON.stringify(savedNotes));
- }
- // Retrieve note for a word
- function getNote(word) {
- const identifier = getWordIdentifier(word);
- const savedNotes = JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}');
- return savedNotes[identifier] || '';
- }
- // Create note popup
- function createNotePopup(word) {
- const popup = document.createElement('div');
- popup.classList.add('ca-note-popup');
- const textarea = document.createElement('textarea');
- textarea.classList.add('ca-note-input');
- textarea.placeholder = `Enter note for "${word}"`;
- textarea.value = getNote(word);
- const buttonContainer = document.createElement('div');
- buttonContainer.classList.add('ca-note-buttons');
- const saveButton = document.createElement('button');
- saveButton.textContent = 'Save';
- saveButton.classList.add('ca-note-save');
- saveButton.addEventListener('click', () => {
- saveNote(word, textarea.value);
- document.body.removeChild(popup);
- });
- const cancelButton = document.createElement('button');
- cancelButton.textContent = 'Discard';
- cancelButton.classList.add('ca-note-cancel');
- cancelButton.addEventListener('click', () => {
- document.body.removeChild(popup);
- });
- buttonContainer.appendChild(saveButton);
- buttonContainer.appendChild(cancelButton);
- popup.appendChild(textarea);
- popup.appendChild(buttonContainer);
- return popup;
- }
- // New function to un-highlight text
- function unhighlightText(element) {
- if (element && element.classList.contains('ca-highlight')) {
- // Get the text content
- const text = element.textContent;
- // Create a text node to replace the highlighted span
- const textNode = document.createTextNode(text);
- // Replace the span with the text node
- element.parentNode.replaceChild(textNode, element);
- }
- }
- // Handle highlighting and un-highlighting with a single click
- function handleHighlightClick(e) {
- // Only work in highlight mode
- if (!isHighlightMode) return;
- // Check if clicked on an existing highlight
- if (e.target.classList && e.target.classList.contains('ca-highlight')) {
- // Un-highlight the text
- unhighlightText(e.target);
- return;
- }
- // Otherwise, create a new highlight
- const selection = window.getSelection();
- const selectedText = selection.toString();
- if (selectedText && selectedText.trim() !== '') {
- try {
- // Get the range
- const range = selection.getRangeAt(0);
- // Store the original text with spaces for note-taking
- const originalText = selectedText;
- // Create a highlight span
- const highlightSpan = document.createElement('span');
- highlightSpan.classList.add('ca-highlight');
- // Use createTextNode to preserve spaces
- highlightSpan.appendChild(document.createTextNode(selectedText));
- // Replace selection with our highlight
- range.deleteContents();
- range.insertNode(highlightSpan);
- // Clear the selection
- selection.removeAllRanges();
- } catch (error) {
- console.error('Error highlighting text:', error);
- }
- }
- }
- // Add right-click handling for highlights
- function handleHighlightRightClick(e) {
- // Check if right-clicked on a highlight
- if (e.target.classList && e.target.classList.contains('ca-highlight')) {
- e.preventDefault();
- // Get the highlighted text
- const highlightedText = e.target.textContent;
- // Create and display a popup menu for the note
- const notePopup = createNotePopup(highlightedText);
- document.body.appendChild(notePopup);
- } else {
- // Add note functionality when not in highlight mode
- if (!isHighlightMode) {
- const selection = window.getSelection();
- const selectedText = selection.toString();
- if (selectedText && selectedText.trim() !== '') {
- e.preventDefault();
- // Create and display a popup menu for the note
- const notePopup = createNotePopup(selectedText);
- document.body.appendChild(notePopup);
- }
- }
- }
- }
- // Toggle highlight mode
- function toggleHighlightMode() {
- isHighlightMode = !isHighlightMode;
- highlightModeIndicator.style.display = isHighlightMode ? 'block' : 'none';
- // Update the indicator text to show the new mode behavior
- highlightModeIndicator.textContent = isHighlightMode ?
- 'Highlight Mode (Click to highlight/unhighlight, Right-click for notes)' :
- 'Highlight Mode';
- }
- // Event listeners
- document.addEventListener('click', (e) => {
- // Single click for highlighting/unhighlighting when in highlight mode
- handleHighlightClick(e);
- });
- document.addEventListener('contextmenu', (e) => {
- // Right-click for adding notes to highlights
- handleHighlightRightClick(e);
- });
- document.addEventListener('keydown', (e) => {
- // Toggle highlight mode with '/'
- if (e.key === '/') {
- e.preventDefault();
- toggleHighlightMode();
- }
- });
- // Add initial message about feature
- console.log('Character.ai Text Highlighter Loaded:\n- Highlight Mode: "/" to toggle\n- While in highlight mode: click to highlight/unhighlight\n- Right-click on highlighted text to add/view notes\n- Right-click on selected text to add notes when not in highlight mode');
- })();