Syosetu Chapter Copy

Copy the chapter content from a Syosetu chapter page.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==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
// ==/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 = "<br /><input type='button' id='UBsyosetuChapterCopyWhole' value='Copy Whole Chapter' />";
    if( charCount > maxChars ) {
        btnElem += "&nbsp;<input type='button' id='UBsyosetuChapterCopyPart' value='Copy Chapter Block: 1 of " + Math.ceil( charCount / ( maxChars - safetyNet ) ) + "' />";
    }

    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;
}




//