Skip to content

Instantly share code, notes, and snippets.

@lunamoth
Last active December 18, 2024 10:47
Show Gist options
  • Save lunamoth/6836fa2912be1424b172d704c6bee846 to your computer and use it in GitHub Desktop.
Save lunamoth/6836fa2912be1424b172d704c6bee846 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name 웹페이지 제목/URL 복사 스크립트
// @namespace http://tampermonkey.net/
// @version 2.8
// @description Alt+1 키를 눌러 현재 페이지의 제목과 URL을, Alt+Q 키를 눌러 URL만 클립보드에 복사합니다.
// @author Claude & Gemini
// @match *://*/*
// @grant GM_setClipboard
// @grant GM_addStyle
// ==/UserScript==
(() => {
'use strict';
const CONFIG = {
KEY_TITLE_URL: '1',
KEY_URL_ONLY: 'q',
POPUP_DURATION_MS: 2000,
POPUP_MESSAGE: '복사 완료',
TITLE_URL_SEPARATOR: '\n\n', // 제목과 URL 사이 구분자
POPUP_TOP: '20px', // 팝업 상단 위치
POPUP_LEFT: '50%', // 팝업 좌측 위치
POPUP_TRANSFORM: 'translateX(-50%)', // 팝업 가로축 이동
POPUP_BACKGROUND_COLOR: '#22A06B', // 팝업 배경색
POPUP_TEXT_COLOR: '#fff', // 팝업 텍스트 색상
POPUP_PADDING: '10px 20px', // 팝업 패딩
POPUP_BORDER_RADIUS: '5px', // 팝업 테두리 반경
POPUP_Z_INDEX: 9999, // 팝업 z-index
};
// 팝업 요소 생성 (한 번만 생성)
const style = `
.copy-popup {
position: fixed;
top: ${CONFIG.POPUP_TOP};
left: ${CONFIG.POPUP_LEFT};
transform: ${CONFIG.POPUP_TRANSFORM};
background-color: ${CONFIG.POPUP_BACKGROUND_COLOR};
color: ${CONFIG.POPUP_TEXT_COLOR};
padding: ${CONFIG.POPUP_PADDING};
border-radius: ${CONFIG.POPUP_BORDER_RADIUS};
z-index: ${CONFIG.POPUP_Z_INDEX};
display: none;
}
`;
GM_addStyle(style);
const popup = document.createElement('div');
popup.className = 'copy-popup';
popup.textContent = CONFIG.POPUP_MESSAGE;
document.body.appendChild(popup);
// DOM 접근 최소화를 위한 변수
let pageTitle = document.title;
let pageURL = window.location.href;
// MutationObserver를 사용하여 document.title 변경 감지
const titleObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'childList' && mutation.target === document.querySelector('title')) {
pageTitle = document.title;
}
});
});
titleObserver.observe(document.querySelector('title'), { childList: true });
// 팝업 표시 함수
const showPopup = () => {
popup.style.display = 'block';
setTimeout(() => {
popup.style.display = 'none';
}, CONFIG.POPUP_DURATION_MS);
};
// 클립보드 복사 함수 (비동기 처리 개선)
const copyToClipboard = (content) => {
// GM_setClipboard가 Promise를 반환하는지 확인 (Tampermonkey API 문서 확인 필요)
const result = GM_setClipboard(content);
if (result instanceof Promise) {
result.then(() => {
showPopup();
});
} else {
showPopup();
}
};
// 웹페이지 정보 (제목 + URL) 복사 함수
const copyWebpageInfo = () => {
const content = pageTitle + CONFIG.TITLE_URL_SEPARATOR + pageURL;
copyToClipboard(content);
};
// 웹페이지 URL만 복사 함수
const copyWebpageUrl = () => {
copyToClipboard(pageURL);
};
// 키 입력 처리 함수 (이벤트 리스너 최적화)
document.addEventListener('keydown', (e) => {
if (e.altKey) {
if (e.key === CONFIG.KEY_TITLE_URL) {
copyWebpageInfo();
} else if (e.key === CONFIG.KEY_URL_ONLY) {
copyWebpageUrl();
}
}
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment