// ==UserScript==
// @name Syosetu Chapter Copy
// @namespace ultrabenosaurus.Syosetu
// @version 0.10
// @description Copy the chapter content from a Syosetu chapter page.
// @author Ultrabenosaurus
// @license GNU AGPLv3
// @source https://greasyfork.org/en/users/437117-ultrabenosaurus?sort=name
// @match https://ncode.syosetu.com/*/*/
// @icon https://www.google.com/s2/favicons?domain=ncode.syosetu.com
// @grant GM.setClipboard
// @grant GM_setClipboard
// @downloadURL https://update.greasyfork.icu/scripts/411100/Syosetu%20Chapter%20Copy.user.js
// @updateURL https://update.greasyfork.icu/scripts/411100/Syosetu%20Chapter%20Copy.meta.js
// ==/UserScript==
(function() {
'use strict';
/*
*
* maxChars: The maximum number of characters to copy at once. If the whole
* chapter is less than maxChars there will only be one button which
* will copy the whole chapter. If it is longer then there will be 2
* buttons, with the second copying "blocks" of maxChars characters.
*
* safetyNet: How many characters to overlap from the previous block. This is
* so that there is some context for your translation tool to work
* with in the case that a sentence would otherwise be cut in half.
*
* e.g. the first block will be 5000 - 100 = 4900 characters, subsequent blocks
* will be 5000 chars including the last 100 chars from the previous block and
* the 4900 of the current block.
*
* Both are also set at the start of the UBsyosetuChapterCopyPart() function.
*
*/
var maxChars = 5000;
var safetyNet = 100;
var mobile = 0;
let txtBox = document.createElement("textarea");
txtBox.id = "UBsyosetuChapterContent";
txtBox.name = "UBsyosetuChapterContent";
txtBox.style = "width: 0; height: 0; border: none;";
document.body.appendChild(txtBox);
var subTitle = document.querySelectorAll('div#novel_color p.novel_subtitle');
if(subTitle.length == 0) {
mobile = 1;
subTitle = document.querySelectorAll('div#novel_color div.novel_subtitle');
}
txtBox.value = (mobile ? subTitle[0].innerText.split("\n")[1] : subTitle[0].textContent) + "\n\n" + document.querySelectorAll('div#novel_honbun')[0].textContent;
var charCount = txtBox.value.length;
var btnElem = " ";
if( charCount > maxChars ) {
btnElem += " ";
}
subTitle[0].insertAdjacentHTML("beforeend", btnElem);
var sccwBtn = document.getElementById('UBsyosetuChapterCopyWhole');
if(sccwBtn){
sccwBtn.addEventListener("click", UBsyosetuChapterCopyWhole, false);
}
var sccpBtn = document.getElementById('UBsyosetuChapterCopyPart');
if(sccpBtn){
sccpBtn.addEventListener("click", UBsyosetuChapterCopyPart, false);
}
maxChars = safetyNet = mobile = sccwBtn = sccpBtn = btnElem = txtBox = subTitle = charCount = null;
})();
function UBsyosetuChapterCopyWhole() {
let txtBox = document.getElementById('UBsyosetuChapterContent');
txtBox.select();
txtBox.setSelectionRange(0, 999999);
document.execCommand("copy");
txtBox = null;
}
function UBsyosetuChapterCopyPart() {
var maxChars = 5000;
var safetyNet = 100;
var copyBtn = document.getElementById('UBsyosetuChapterCopyPart');
var chpPart = parseInt( copyBtn.value.split(": ")[1].split(" of ")[0] );
var lastPart = parseInt( copyBtn.value.split(": ")[1].split(" of ")[1] );
let txtBox = document.getElementById('UBsyosetuChapterContent');
var maxBlocks = Math.ceil( txtBox.value.length / ( maxChars - safetyNet ) );
if( maxBlocks >= chpPart ) {
var selRngStart = ( chpPart - 1 ) * ( maxChars - safetyNet );
selRngStart = chpPart > 1 ? selRngStart - safetyNet : selRngStart;
var selRngEnd = chpPart * ( maxChars - safetyNet );
txtBox.select();
txtBox.setSelectionRange( selRngStart, selRngEnd );
document.execCommand("copy");
copyBtn.value = copyBtn.value.split(": ")[0] + ": " + ( chpPart + 1 ) + " of " + lastPart;
} else {
copyBtn.value = copyBtn.value.split(": ")[0] + ": 1 of " + lastPart;
alert("You have already finished this chapter. Click again to start copying from the first block.");
}
maxChars = safetyNet = maxBlocks = copyBtn = chpPart = lastPart = selRngStart = selRngEnd = txtBox = null;
}
//