// ==UserScript== // @name GoodNote - 网页笔记助手 // @namespace http://tampermonkey.net/ // @version 0.5b1 // @description 在任何网页添加笔记功能 // @author kasusa // @license MIT // @match *://*/* // @icon https://www.google.com/s2/favicons?sz=64&domain=greasyfork.org // @grant GM_setValue // @grant GM_getValue // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 创建样式 const style = document.createElement('style'); style.textContent = ` .note-icon { /* 背景颜色 */ backdrop-filter: blur(10px); background-color: #ffffff00; border: 1px solid #ffffff8f; /* 圆角 */ border-radius: 3px; /* 固定位置 */ position: fixed; /* 默认位置 */ top: 20px; right: 20px; /* 大小 */ width: 20px; height: 20px; cursor: move; z-index: 9999; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 5px rgba(0,0,0,0.2); transition: 0.1s ease; user-select: none; will-change: transform; transform: translate3d(0, 0, 0); opacity: 1; pointer-events: auto; } .note-icon:hover { transform: scale(1); } .note-icon:active { transform: scale(0.9); } .note-icon svg { width: 24px; height: 24px; fill: #409eff; } .note-container { border: 1px solid #fff; position: fixed; backdrop-filter: blur(10px); border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); z-index: 9998; padding: 10px; transition: all 0.3s ease; opacity: 0; transform-origin: center; pointer-events: auto; display: none; } .note-container.active { opacity: 1; transform: scale(1); } .note-textarea { margin-bottom: 0 !important; background: #fff; color:#000; min-height: 250px; border: 1px solid #ddd; border-radius: 4px; padding: 12px; font-size: 14px; resize: both; overflow: auto; font-family: Arial, sans-serif; line-height: 1.5; min-width: 350px; word-break: break-all; text-align: left; } .note-textarea:focus { outline: none; } .note-icon::after { content: 'Ctrl+Shift+M'; position: absolute; background: rgba(255, 255, 255, 0.61); backdrop-filter: blur(15px); color: #000; padding: 5px 8px; border-radius: 4px; font-size: 12px; white-space: nowrap; right: 100%; top: 50%; transform: translateY(-50%); margin-right: 10px; opacity: 0; transition: opacity 0.2s; pointer-events: none; border: 1px solid rgba(255, 255, 255, 0.2); } .note-icon:hover::after { opacity: 1; } .goodnote-wrapper { position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 9998; } .note-textarea a { color: #409EFF; text-decoration: underline; cursor: pointer; } .note-textarea a:hover { opacity: 0.8; } `; document.head.appendChild(style); // 创建笔记图标 const noteIcon = document.createElement('div'); noteIcon.className = 'note-icon'; // 根据平台设置不同的快捷键提示 const isMac = /Mac|iPod|iPhone|iPad/.test(navigator.platform); noteIcon.setAttribute('data-shortcut', isMac ? '⌘+Shift+M' : 'Ctrl+Shift+M'); // 修改样式内容,使用动态快捷键文本 const shortcutText = isMac ? '⌘+Shift+M' : 'Ctrl+Shift+M'; style.textContent = style.textContent.replace( '.note-icon::after { content: \'Ctrl+Shift+M\';', `.note-icon::after { content: '${shortcutText}';` ); noteIcon.innerHTML = ` `; // 创建笔记容器 const noteContainer = document.createElement('div'); noteContainer.className = 'note-container'; // 创建文本框 const textarea = document.createElement('div'); textarea.className = 'note-textarea'; textarea.contentEditable = true; textarea.placeholder = '在这里输入你的笔记...'; noteContainer.appendChild(textarea); // 创建一个包装器元素 const wrapper = document.createElement('div'); wrapper.className = 'goodnote-wrapper'; document.body.appendChild(wrapper); // 将笔记图标和容器添加到包装器中,而不是直接添加到 body wrapper.appendChild(noteIcon); wrapper.appendChild(noteContainer); // 获取当前域名作为存储键 const storageKey = `goodnote_${window.location.hostname}`; const positionKey = `goodnote_position_${window.location.hostname}`; // 在创建textarea的部分后添加以下函数 function linkify(text) { const urlRegex = /(https?:\/\/[^\s]+)/g; return text.replace(urlRegex, function(url) { return `${url}`; }); } // 添加链接点击处理 textarea.addEventListener('click', (e) => { if (e.target.tagName === 'A') { e.preventDefault(); window.open(e.target.href, '_blank'); } }); // 防止链接编辑时被触发 textarea.addEventListener('mousedown', (e) => { if (e.target.tagName === 'A') { if (e.detail >= 2) { // 双击或更多次点击时允许编辑 e.preventDefault(); } } }); // 修改input事件监听器 textarea.addEventListener('input', () => { clearTimeout(saveTimeout); saveTimeout = setTimeout(() => { const content = textarea.innerHTML; localStorage.setItem(storageKey, content); }, 500); }); // 修改加载保存的笔记的部分 const savedNote = localStorage.getItem(storageKey); if (savedNote) { textarea.innerHTML = savedNote; } // 添加一个函数来获取网页标题 async function fetchPageTitle(url) { try { const response = await fetch(url); const text = await response.text(); const doc = new DOMParser().parseFromString(text, 'text/html'); return doc.querySelector('title').innerText; } catch (error) { console.error('Error fetching page title:', error); return null; } } // 修改粘贴事件处理 textarea.addEventListener('paste', async (e) => { e.preventDefault(); const text = e.clipboardData.getData('text/plain'); const processed_text = linkify(text); document.execCommand('insertHTML', false, processed_text); // 获取并处理标题 const urlRegex = /(https?:\/\/[^\s]+)/g; const match = urlRegex.exec(text); if (match) { const url = match[0]; const title = await fetchPageTitle(url); if (title) { // 只保留标题的第一个部分 const [mainTitle] = title.split(' - '); // 在链接的下一行插入标题 const titleHTML = `