はじめに
ローカルPCにあるMarkdown形式のドキュメントを読んでいる時に、コードブロックをコピーするのが面倒だったので、コピーボタンを自動で追加するChrome拡張機能を生成AI作成してみました。
実装する機能
- Markdownのコードブロック箇所にコピーボタンを自動で追加する
- GitHubやQiitaなど、既にコピーボタンがあるサイトでは表示しない制御ができるようにする
- ボタンをクリックするとその内容をクリップボードにコピーする
用意するファイル
1. manifest.json
{
"manifest_version": 3,
"name": "Markdown Code Copy",
"version": "1.0",
"description": "Add copy buttons to markdown code blocks",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"],
"css": ["styles.css"],
"all_frames": true
}
],
"permissions": ["activeTab"],
"host_permissions": ["file://*/*"]
}
2. content.js
// 除外するサイトのリスト
const excludedSites = [
'github.com',
'qiita.com',
'zenn.dev',
'stackoverflow.com'
];
// 現在のサイトが除外対象かチェック
function isExcludedSite() {
const hostname = window.location.hostname;
// ローカルファイル(file://)の場合はhostnameが空文字になるので除外しない
if (window.location.protocol === 'file:') {
return false;
}
// hostnameが空の場合(ローカルファイル等)は除外しない
if (!hostname) {
return false;
}
return excludedSites.some(site => hostname.includes(site));
}
// デバッグ用ログ(開発時のみ使用)
function debugLog() {
console.log('Current URL:', window.location.href);
console.log('Protocol:', window.location.protocol);
console.log('Hostname:', window.location.hostname);
console.log('Is excluded:', isExcludedSite());
}
// コードブロックを検出してコピーボタンを追加
function addCopyButtons() {
// デバッグログ(必要に応じてコメントアウト)
debugLog();
// 除外サイトの場合は何もしない
if (isExcludedSite()) {
console.log('Site is excluded, skipping...');
return;
}
const codeBlocks = document.querySelectorAll('pre code, pre, code');
console.log('Found code blocks:', codeBlocks.length);
codeBlocks.forEach((block, index) => {
// 既にボタンが追加されている場合はスキップ
if (block.parentElement.querySelector('.copy-btn')) {
console.log(`Block ${index}: Already has copy button`);
return;
}
// 複数行のコードブロックのみ対象
if (block.textContent.split('\n').length < 2) {
console.log(`Block ${index}: Single line, skipping`);
return;
}
console.log(`Block ${index}: Adding copy button`);
const copyBtn = document.createElement('button');
copyBtn.textContent = 'Copy';
copyBtn.className = 'copy-btn';
copyBtn.onclick = () => copyToClipboard(block.textContent);
// ボタンの配置
const wrapper = block.parentElement;
wrapper.style.position = 'relative';
wrapper.appendChild(copyBtn);
});
}
// クリップボードにコピー
async function copyToClipboard(text) {
try {
await navigator.clipboard.writeText(text);
showCopyFeedback();
} catch (err) {
// フォールバック方法
const textArea = document.createElement('textarea');
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
showCopyFeedback();
}
}
// コピー完了のフィードバック
function showCopyFeedback() {
const feedback = document.createElement('div');
feedback.textContent = 'Copied!';
feedback.className = 'copy-feedback';
document.body.appendChild(feedback);
setTimeout(() => {
document.body.removeChild(feedback);
}, 2000);
}
// ページ読み込み時とDOM変更時に実行
addCopyButtons();
const observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
3. styles.css
.copy-btn {
position: absolute;
top: 8px;
right: 8px;
background: #24292e;
color: white;
border: none;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
cursor: pointer;
opacity: 0.7;
transition: opacity 0.2s;
}
.copy-btn:hover {
opacity: 1;
}
.copy-feedback {
position: fixed;
top: 20px;
right: 20px;
background: #28a745;
color: white;
padding: 8px 16px;
border-radius: 4px;
z-index: 10000;
animation: fadeInOut 2s ease-in-out;
}
@keyframes fadeInOut {
0%, 100% { opacity: 0; }
10%, 90% { opacity: 1; }
}
インストール方法
- 新しいフォルダを作成して上記の3ファイルを保存する
- Chromeで
chrome://extensions/
にアクセス - 右上の「デベロッパーモード」を有効にする
- 「パッケージ化されていない拡張機能を読み込む」をクリック
- 手順の1で作成したフォルダを選択する
- 重要: ローカルPCのMarkdownファイルで利用する場合は、拡張機能の詳細ページで「ファイルの URL へのアクセスを許可する」をONにする
完成イメージ
- ローカルPCにあるMarkdownファイルをChrome開くと、コードブロックの右端にCopyボタンが追加されました。
- また、content.jsの除外サイトに「qiita.com」があるので、以下のコードブロックにはCopyボタンは表示されず、ちゃんと制御されていることがわかります。
このコードブロックにはコピーボタンは表示されません。
カスタマイズ(除外サイトの追加)
- コピーボタンを表示したくないサイトを追加する場合は、content.jsの以下の箇所に対象サイトのドメインを追加してください
const excludedSites = [
'github.com',
'qiita.com',
'zenn.dev',
'stackoverflow.com',
'ほげほげ.com' // 追加
];
まとめ
Chrome拡張機能でMarkdownコードブロックを効率的にコピーできるようになりました。
作業の生産性向上に貢献できればうれしいです。
ぜひお試しください。