您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
One-click clipboard quote → GitHub Gist, with keyword highlighting
当前为
- // ==UserScript==
- // @name Clip-to-Gist
- // @name:zh-CN Clip-to-Gist 金句剪贴脚本(v2)
- // @namespace https://github.com/yourusername
- // @version 2.0
- // @description One-click clipboard quote → GitHub Gist, with keyword highlighting
- // @description:zh-CN 一键剪贴板金句并上传至 GitHub Gist,支持关键词标注和高亮
- // @author Your Name
- // @match *://*/*
- // @grant GM_setValue
- // @grant GM_getValue
- // @grant GM_xmlhttpRequest
- // @grant GM_addStyle
- // @grant GM_registerMenuCommand
- // @license MIT
- // ==/UserScript==
- (function() {
- 'use strict';
- // 注册(不可用)菜单:配置 Gist 参数
- GM_registerMenuCommand('配置 Gist 参数', openConfigModal);
- // 注入右下角触发按钮
- const trigger = document.createElement('div');
- trigger.id = 'clip2gist-trigger';
- trigger.textContent = '📝';
- document.body.appendChild(trigger);
- // 样式
- GM_addStyle(`
- #clip2gist-trigger {
- position: fixed; bottom: 20px; right: 20px;
- width: 40px; height: 40px; line-height: 40px;
- background: #4CAF50; color: #fff; text-align: center;
- border-radius: 50%; cursor: pointer; z-index: 9999;
- font-size: 24px;
- }
- .clip2gist-mask {
- position: fixed; inset: 0; background: rgba(0,0,0,0.5);
- display: flex; align-items: center; justify-content: center;
- z-index: 10000;
- }
- .clip2gist-dialog {
- background: #fff; padding: 20px; border-radius: 8px;
- max-width: 90%; max-height: 90%; overflow: auto;
- box-shadow: 0 2px 10px rgba(0,0,0,0.3);
- }
- .clip2gist-dialog input {
- width: 100%; padding: 6px; margin-top: 4px; margin-bottom: 12px;
- box-sizing: border-box; font-size: 14px;
- }
- .clip2gist-dialog button {
- margin-left: 8px; padding: 6px 12px; font-size: 14px;
- }
- .clip2gist-word {
- display: inline-block; margin: 2px; padding: 4px 6px;
- border: 1px solid #ccc; border-radius: 4px; cursor: pointer;
- user-select: none;
- }
- .clip2gist-word.selected {
- background: #ffeb3b; border-color: #f1c40f;
- }
- #clip2gist-preview {
- margin-top: 12px; padding: 8px; border: 1px solid #ddd;
- min-height: 40px; font-family: monospace;
- }
- `);
- trigger.addEventListener('click', mainFlow);
- async function mainFlow() {
- let text = '';
- try {
- text = await navigator.clipboard.readText();
- } catch (e) {
- return alert('请在 HTTPS 环境并授权剪贴板访问');
- }
- if (!text.trim()) return alert('剪贴板内容为空');
- showEditDialog(text.trim());
- }
- function showEditDialog(rawText) {
- const mask = document.createElement('div');
- mask.className = 'clip2gist-mask';
- const dlg = document.createElement('div');
- dlg.className = 'clip2gist-dialog';
- // 词块化
- const wordContainer = document.createElement('div');
- rawText.split(/\s+/).forEach(w => {
- const sp = document.createElement('span');
- sp.className = 'clip2gist-word';
- sp.textContent = w;
- sp.addEventListener('click', () => {
- sp.classList.toggle('selected');
- updatePreview();
- });
- wordContainer.appendChild(sp);
- });
- dlg.appendChild(wordContainer);
- // 预览区
- const preview = document.createElement('div');
- preview.id = 'clip2gist-preview';
- dlg.appendChild(preview);
- // 按钮行
- const btnRow = document.createElement('div');
- const cancelBtn = document.createElement('button');
- cancelBtn.textContent = '取消';
- cancelBtn.addEventListener('click', () => document.body.removeChild(mask));
- const configBtn = document.createElement('button');
- configBtn.textContent = '配置';
- configBtn.addEventListener('click', openConfigModal);
- const confirmBtn = document.createElement('button');
- confirmBtn.textContent = '确认';
- confirmBtn.addEventListener('click', onConfirm);
- btnRow.append(cancelBtn, configBtn, confirmBtn);
- dlg.appendChild(btnRow);
- mask.appendChild(dlg);
- document.body.appendChild(mask);
- updatePreview();
- function updatePreview() {
- const spans = Array.from(wordContainer.children);
- const final = [];
- for (let i = 0; i < spans.length;) {
- if (spans[i].classList.contains('selected')) {
- const group = [spans[i].textContent];
- let j = i + 1;
- while (j < spans.length && spans[j].classList.contains('selected')) {
- group.push(spans[j].textContent);
- j++;
- }
- final.push(`{${group.join(' ')}}`);
- i = j;
- } else {
- final.push(spans[i].textContent);
- i++;
- }
- }
- preview.textContent = final.join(' ');
- }
- async function onConfirm() {
- const gistId = await GM_getValue('gistId');
- const token = await GM_getValue('githubToken');
- if (!gistId || !token) {
- return alert('请先通过“配置 Gist 参数”填写 Gist ID 与 Token');
- }
- const content = preview.textContent;
- GM_xmlhttpRequest({
- method: 'GET',
- url: `https://api.github.com/gists/${gistId}`,
- headers: { Authorization: `token ${token}` },
- onload(resp1) {
- if (resp1.status !== 200) return alert('拉取 Gist 失败');
- const data = JSON.parse(resp1.responseText);
- const fname = Object.keys(data.files)[0];
- const old = data.files[fname].content;
- const updated = `\n\n----\n${content}` + old;
- GM_xmlhttpRequest({
- method: 'PATCH',
- url: `https://api.github.com/gists/${gistId}`,
- headers: {
- Authorization: `token ${token}`,
- 'Content-Type': 'application/json'
- },
- data: JSON.stringify({ files: { [fname]: { content: updated } } }),
- onload(resp2) {
- if (resp2.status === 200) {
- alert('上传成功 🎉');
- document.body.removeChild(mask);
- } else {
- alert('上传失败:' + resp2.status);
- }
- }
- });
- }
- });
- }
- }
- function openConfigModal() {
- const mask = document.createElement('div');
- mask.className = 'clip2gist-mask';
- const dlg = document.createElement('div');
- dlg.className = 'clip2gist-dialog';
- const idLabel = document.createElement('label');
- idLabel.textContent = 'Gist ID:';
- const idInput = document.createElement('input');
- idInput.value = GM_getValue('gistId', '');
- const tkLabel = document.createElement('label');
- tkLabel.textContent = 'GitHub Token:';
- const tkInput = document.createElement('input');
- tkInput.value = GM_getValue('githubToken', '');
- dlg.append(idLabel, idInput, tkLabel, tkInput);
- const saveBtn = document.createElement('button');
- saveBtn.textContent = '保存';
- saveBtn.addEventListener('click', () => {
- GM_setValue('gistId', idInput.value.trim());
- GM_setValue('githubToken', tkInput.value.trim());
- alert('配置已保存');
- document.body.removeChild(mask);
- });
- const cancelBtn2 = document.createElement('button');
- cancelBtn2.textContent = '取消';
- cancelBtn2.addEventListener('click', () => document.body.removeChild(mask));
- dlg.append(saveBtn, cancelBtn2);
- mask.appendChild(dlg);
- document.body.appendChild(mask);
- }
- })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址