Skip to content

Instantly share code, notes, and snippets.

@tsantos8080
Created July 29, 2026 15:46
Show Gist options
  • Select an option

  • Save tsantos8080/2352308c49ee8b820118a21acb1439c4 to your computer and use it in GitHub Desktop.

Select an option

Save tsantos8080/2352308c49ee8b820118a21acb1439c4 to your computer and use it in GitHub Desktop.
Kanji Koohii Story Copier
// ==UserScript==
// @name Kanji Koohii Story Copier
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Intercepts copy buttons on Kanji Koohii to copy story HTML directly to clipboard
// @author You
// @match https://kanji.koohii.com/study/kanji/*
// @grant GM_setClipboard
// ==/UserScript==
(function() {
'use strict';
// Inject Toast Styles
const style = document.createElement('style');
style.innerHTML = `
#koohii-toast {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 9999;
background-color: #2e7d32;
color: #ffffff;
padding: 10px 16px;
border-radius: 6px;
font-family: sans-serif;
font-size: 13px;
box-shadow: 0 2px 8px rgba(0,0,0,0.2);
opacity: 0;
transform: translateY(10px);
transition: opacity 0.3s ease, transform 0.3s ease;
pointer-events: none;
}
#koohii-toast.show {
opacity: 1;
transform: translateY(0);
}
`;
document.head.appendChild(style);
// Create Toast element
const toast = document.createElement('div');
toast.id = 'koohii-toast';
toast.innerText = 'Story copied to clipboard!';
document.body.appendChild(toast);
function showToast(msg) {
toast.innerText = msg || 'Story copied to clipboard!';
toast.classList.add('show');
setTimeout(() => {
toast.classList.remove('show');
}, 2000);
}
function copyToClipboard(text) {
if (typeof GM_setClipboard !== 'undefined') {
GM_setClipboard(text);
} else {
navigator.clipboard.writeText(text);
}
}
// Event listener using capture phase to intercept the click before site scripts run
document.addEventListener('click', function(event) {
const copyBtn = event.target.closest('.sharedstory_btn.JsCopy');
if (copyBtn) {
// Stop native Kanji Koohii copy behavior
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
// Find the parent story block and extract the .story innerHTML
const sharedStory = copyBtn.closest('.sharedstory');
if (sharedStory) {
const storyElem = sharedStory.querySelector('.story');
if (storyElem) {
copyToClipboard(storyElem.innerHTML.trim());
showToast('Story copied!');
}
}
}
}, true); // The 'true' enables the capture phase
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment