您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add zoom button in github comment to provide full screen mode, allowing you to write comments more elegantly
// ==UserScript== // @name Comment Zoomer // @namespace http://tampermonkey.net/ // @version 1.0.1 // @description Add zoom button in github comment to provide full screen mode, allowing you to write comments more elegantly // @author IsaacKam // @match https://github.com/* // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; const namespace = '__ISSUE_EDITOR__'; const emToggleState = { IDLE: '', NORMAL: 'normal', FULL_SCREEN: 'full_screen' }; const emPreviewState = { IDLE: '', NORMAL: 'normal', PREVIEW: 'preview' }; const store = { sup: null, previewTimer: 0, toggleStatus: emToggleState.IDLE, previewStatus: emPreviewState.IDLE }; const initStyle = () => { const style = document.createElement('style'); const cssText = document.createTextNode(` .issue-editor__body--disable-scroll { overflow: hidden; } .issue-editor__entry-btn { display: inline-block; cursor: pointer; user-select: none; color: rgb(87, 96, 106); margin-left: 8px; vertical-align: top; } .issue-editor__caret { position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 1001; } .issue-editor__textarea { max-height: none !important; height: calc(100vh - 200px) !important; } .issue-editor__file-attachment { margin-left: 15px; } .issue-editor__file-attachment--preview { width: 50vw; } .issue-editor__file-attachment-write-content--preview { display: block !important; } .issue-editor__preview-content--preview { width: 50vw; margin-left: calc(50vw + 8px) !important; display: block !important; position: absolute; top: 56px; height: calc(100vh - 170px) !important; overflow: auto; border: 1px solid darkturquoise; border-radius: 2px; } markdown-toolbar.issue-editor__markdown-toolbar { display: block !important; } `); style.appendChild(cssText); document.head.appendChild(style); }; const nodes = {}; const intiGetter = (get) => ({ get }); Object.defineProperties(nodes, { discussionBucket: intiGetter( () => document.querySelector("#discussion_bucket")), caret: intiGetter( () => store.sup.querySelector(".timeline-comment--caret")), markdownToolbar: intiGetter( () => store.sup.querySelector("markdown-toolbar")), textarea: intiGetter( () => store.sup.querySelector("textarea.js-comment-field")), commentFormActions: intiGetter( () => store.sup.querySelector('.comment-form-actions')), newCommentSup: intiGetter( () => nodes.discussionBucket.querySelector('.discussion-timeline-actions')), newCommentFormActions: intiGetter( () => nodes.newCommentSup.querySelector('#partial-new-comment-form-actions')), fileAttachment: intiGetter( () => store.sup.querySelector('file-attachment')), fileAttachmentWriteContent: intiGetter( () => nodes.fileAttachment.querySelector('.write-content')), previewContent: intiGetter( () => store.sup.querySelector('.preview-content')), previewEntery: intiGetter( () => store.sup.querySelector('.issue-editor__preview-btn')), updateEntery: intiGetter( () => store.sup.querySelector('.issue-editor__update-btn')), previewTab: intiGetter( () => store.sup.querySelector('.preview-tab')), writeTab: intiGetter( () => store.sup.querySelector('.write-tab')), }); window[namespace] = {}; window[namespace].store = store; window[namespace].nodes = nodes; function addClass({ node, classname }) { const classSet = new Set(node.classList); classSet.add(classname); node.setAttribute('class', Array.from(classSet).join(' ')); } function removeClass({ node, classname }) { const classSet = new Set(node.classList); classSet.delete(classname); node.setAttribute('class', Array.from(classSet).join(' ')); } function fullScreen() { store.toggleStatus = emToggleState.FULL_SCREEN; addClass({ node: document.body, classname: 'issue-editor__body--disable-scroll' }); addClass({ node: nodes.caret, classname: 'issue-editor__caret' }); addClass({ node: nodes.textarea, classname: 'issue-editor__textarea' }); addClass({ node: nodes.fileAttachment, classname: 'issue-editor__file-attachment' }); appendPreviewEntery(); Object.assign(nodes.markdownToolbar.style, { display: 'block !important' }); nodes.textarea.focus(); } function normalScreen() { store.toggleStatus = emToggleState.NORMAL; removeClass({ node: document.body, classname: 'issue-editor__body--disable-scroll' }); removeClass({ node: nodes.caret, classname: 'issue-editor__caret' }); removeClass({ node: nodes.textarea, classname: 'issue-editor__textarea' }); removeClass({ node: nodes.fileAttachment, classname: 'issue-editor__file-attachment' }); removePreviewEntry(); } function setPreviewMode() { store.previewStatus = emPreviewState.PREVIEW; addClass({ node: nodes.fileAttachment, classname: 'issue-editor__file-attachment--preview' }); addClass({ node: nodes.fileAttachmentWriteContent, classname: 'issue-editor__file-attachment-write-content--preview' }); addClass({ node: nodes.previewContent, classname: 'issue-editor__preview-content--preview' }); addClass({ node: nodes.markdownToolbar, classname: 'issue-editor__markdown-toolbar' }); nodes.previewTab.click(); appendEntry({ text: 'Update', classname: 'issue-editor__update-btn', onclick() { nodes.previewTab.click(); } }); Object.assign(nodes.markdownToolbar.style, { display: 'block !important' }); nodes.markdownToolbar.setAttribute('style', 'display: block !important'); } function removePreviewMode() { store.previewStatus = emPreviewState.NORMAL; removeClass({ node: nodes.fileAttachment, classname: 'issue-editor__file-attachment--preview' }); removeClass({ node: nodes.fileAttachmentWriteContent, classname: 'issue-editor__file-attachment-write-content--preview' }); removeClass({ node: nodes.previewContent, classname: 'issue-editor__preview-content--preview' }); removeClass({ node: nodes.markdownToolbar, classname: 'issue-editor__markdown-toolbar' }); removeEntry(nodes.updateEntery); nodes.writeTab.click(); nodes.writeTab.focus(); clearTimeout(store.previewTimer); } function interceptCommentFormActions(node) { node.onclick = () => { if (store.toggleStatus !== emToggleState.FULL_SCREEN) { return; } normalScreen(); }; interceptSubmitComment(node); } function interceptSubmitComment(node) { const submit = node.querySelector('[type=submit]'); const oldSubmitClick = submit.click; submit.onclick = () => { oldSubmitClick(); setTimeout(() => { location.reload(); }, 500); } } function appendEntry({ text, classname, onclick }) { const isExist = nodes.markdownToolbar.querySelector('.' + classname); if (isExist) { return; } const node = document.createElement('div'); const classnameSet = new Set(['issue-editor__entry-btn', classname]); addClass({ node, classname: Array.from(classnameSet).join(' ') }) node.innerHTML = text; if (onclick) { node.onclick = onclick; } nodes.markdownToolbar.append(node); return node; } function appendZoomEntry(sup) { const zoom = appendEntry({ text: 'Zoom', classname: 'issue-editor__zoom-btn', onclick() { console.info('[node.onclick] invoked!'); if (store.toggleStatus === emToggleState.FULL_SCREEN) { normalScreen(); return; } store.sup =sup; fullScreen(); } }); return zoom; } function appendPreviewEntery() { appendEntry({ text: 'Preview', classname: 'issue-editor__preview-btn', onclick() { if (store.previewStatus === emPreviewState.PREVIEW) { removePreviewMode(); return; } setPreviewMode(); } }); } function removeEntry(node) { if (!node) { return; } node.onclick = null; node.parentElement.removeChild(node); } function removePreviewEntry() { removeEntry(nodes.previewEntery) removePreviewMode(); clearTimeout(store.previewTimer); } function initHistoryCommentEntries() { const parent = nodes.discussionBucket.querySelector(".js-discussion.js-socket-channel"); const findEditBtn = (node) => node.querySelector('.js-comment-edit-button'); const findAllTimelineItem = (node) => Array.from(node.querySelectorAll('.js-timeline-item')); const loopFindEditBtn = (it, cb) => { const editBtn = findEditBtn(it); if (editBtn) { cb(editBtn); return; } setTimeout(() => { loopFindEditBtn(it, cb) }, 200); }; const findDetailBtn = (node) => node.querySelectorAll('details')[1]; const getItem = (sup) => ({ sup, sub: findDetailBtn(sup) }); const main = parent.children[0]; const rest = parent.children[1]; const items = [ getItem(main), ...findAllTimelineItem(rest).map(it => getItem(it)) ].filter(it => it.sub); for (const it of items) { it.sub.onclick = () => { it.sub.onclick = null; loopFindEditBtn(it.sub, (editBtn) => { editBtn.onclick = () => { store.sup = it.sup; appendZoomEntry(it.sup); interceptCommentFormActions(nodes.commentFormActions); } }); }; } } function initNewCommentEntry() { store.sup = nodes.newCommentSup; appendZoomEntry(nodes.newCommentSup); interceptCommentFormActions(nodes.newCommentFormActions); } function ready(cb) { if (nodes.discussionBucket) { return setTimeout(cb, 200); } setTimeout(() => ready(cb), 200) } ready(() => { console.info('invoked Issue Editor!'); initStyle(); initNewCommentEntry(); initHistoryCommentEntries(); }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址