您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add a small floating button at bottom-right; click or Alt+C to copy Notion page HTML.
// ==UserScript== // @name Copy Notion Page Content (Bottom-Right Button) // @namespace https://notion.so // @version 0.3 // @description Add a small floating button at bottom-right; click or Alt+C to copy Notion page HTML. // @author YI_XUAN // @match https://www.notion.so/* // @match https://*.notion.site/* // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/turndown.min.js // @run-at document-idle // @grant none // @license MIT // ==/UserScript== (() => { 'use strict'; /* ---------- Toast ---------- */ const toast = msg => { let box = document.getElementById('__copy_notion_toast__'); if (!box) { box = document.createElement('div'); box.id = '__copy_notion_toast__'; box.style.cssText = 'position:fixed;bottom:20px;right:20px;z-index:999999;display:flex;flex-direction:column;gap:8px;pointer-events:none'; document.body.appendChild(box); } const el = document.createElement('div'); el.style.cssText = 'background:#333;color:#fff;padding:6px 12px;font-size:14px;border-radius:4px;opacity:0;transition:opacity .25s'; el.textContent = msg; box.appendChild(el); requestAnimationFrame(() => (el.style.opacity = '1')); setTimeout(() => { el.style.opacity = '0'; el.addEventListener('transitionend', () => el.remove(), { once: true }); }, 2500); }; /* ---------- 复制工具(带 fallback) ---------- */ const copyText = txt => navigator.clipboard?.writeText(txt).catch(() => fallback(txt)) || fallback(txt); const fallback = txt => new Promise(res => { const ta = Object.assign(document.createElement('textarea'), { value: txt, style: 'position:fixed;top:-9999px', }); document.body.appendChild(ta); ta.select(); document.execCommand('copy'); ta.remove(); res(); }); /* ---------- 核心复制逻辑 ---------- */ const copyPageAsMarkdown = () => { const root = document.querySelector('.notion-page-content'); if (!root) return toast('❌ 未找到页面正文'); // —— Turndown 此时已经随 @require 注入完毕 —— const t = new TurndownService({ codeBlockStyle: 'fenced', headingStyle: 'atx', hr: '---', }); const md = t.turndown(root.innerHTML); copyText(md) .then(() => toast('✅ Markdown 已复制')) .catch(e => toast('❌ 复制失败: ' + e)); }; /* ---------- 添加右下角按钮 ---------- */ const addFloatingBtn = () => { if (document.getElementById('__copy_notion_btn__')) return; const btn = document.createElement('button'); btn.id = '__copy_notion_btn__'; btn.title = '复制 Markdown (Alt+C)'; btn.textContent = '📝'; btn.style.cssText = ` position:fixed; bottom:20px; right:20px; z-index:1000000; width:44px;height:44px; font-size:22px; border:none;border-radius:50%; background:#4f46e5;color:#fff; cursor:pointer; box-shadow:0 3px 6px rgba(0,0,0,.2); transition:opacity .2s,transform .2s; `; btn.onmouseenter = () => (btn.style.transform = 'scale(1.08)'); btn.onmouseleave = () => (btn.style.transform = 'scale(1)'); btn.onclick = copyPageAsMarkdown; document.body.appendChild(btn); }; /* ---------- 快捷键 ---------- */ window.addEventListener('keydown', e => { if (e.altKey && e.code === 'KeyC') { e.preventDefault(); copyPageAsMarkdown(); } }); /* ---------- 当 Notion 单页应用切换时重新注入按钮 ---------- */ const observer = new MutationObserver(() => addFloatingBtn()); observer.observe(document, { childList: true, subtree: true }); addFloatingBtn(); })();