Skip to content

Instantly share code, notes, and snippets.

@MarvNC
Last active February 10, 2024 10:47
Show Gist options
  • Save MarvNC/5631b380af2c7c1483e05989cdbef77b to your computer and use it in GitHub Desktop.
Save MarvNC/5631b380af2c7c1483e05989cdbef77b to your computer and use it in GitHub Desktop.
Ex tags to MD
// ==UserScript==
// @name Copy Tags to MangaDex
// @namespace Violentmonkey Scripts
// @match https://exhentai.org/g/*
// @match https://e-hentai.org/g/*
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// @version 1.11
// @author Marv
// @description Copies tags in a format for MD descriptions.
// ==/UserScript==
const defaultAvoidNamespaces = ['language:', 'reclass:', 'temp'];
const addBtnHTML = /* html */ `<div class="copyTagsButton">Copy MD Desc</div>`;
const addCSS = /* css */ `
.copyTagsButton {
height: 50px;
width: 100%;
font-size: 20px;
background-color: #37A2F6;
color: white;
border: none;
transition: all 0.2s ease-in-out;
text-align: center;
line-height: 50px;
cursor: pointer;
}
.namespaceLabel {
cursor: pointer;
}
`;
let avoidNamespaces;
(async function () {
GM_addStyle(addCSS);
avoidNamespaces = GM_getValue('avoidNamespaces', defaultAvoidNamespaces);
console.log('avoidNamespaces', avoidNamespaces);
const rightPanel = document.getElementById('gd5');
const tagsPanel = document.getElementById('gd4');
const addBtn = createElementFromHTML(addBtnHTML);
addBtn.addEventListener('click', () => {
const descString = getMdDesc();
copyTextToClipboard(descString);
});
// insert at beginning of tags panel
tagsPanel.insertBefore(addBtn, tagsPanel.firstElementChild);
// set up toggles for namespaces
const namespaceRows = [...tagsPanel.querySelectorAll('#taglist tr')];
for (const tr of namespaceRows) {
const namespaceLabel = tr.firstElementChild;
namespaceLabel.dataset.namespace = namespaceLabel.innerText;
namespaceLabel.classList.add('namespaceLabel');
toggle(namespaceLabel);
namespaceLabel.addEventListener('click', (e) => {
toggle(namespaceLabel, true);
});
}
})();
/**
* Toggles the namespace label being used.
* @param {HTMLElement} namespaceElem The namespace label element.
* @param {boolean} toggle Whether to toggle the namespace.
*/
function toggle(namespaceElem, toggle = false) {
// check if enabled, toggle if necessary
let enabled = !avoidNamespaces.includes(namespaceElem.dataset.namespace);
if (toggle) {
enabled = !enabled;
}
const check = enabled ? '✅' : '❌';
namespaceElem.innerText = `${namespaceElem.dataset.namespace} ${check}`;
// update avoidNamespaces if needed
if (toggle) {
if (enabled && avoidNamespaces.includes(namespaceElem.dataset.namespace)) {
avoidNamespaces = avoidNamespaces.filter(
(namespace) => namespace !== namespaceElem.dataset.namespace
);
} else if (!avoidNamespaces.includes(namespaceElem.dataset.namespace)) {
avoidNamespaces.push(namespaceElem.dataset.namespace);
}
// set
GM_setValue('avoidNamespaces', avoidNamespaces);
console.log(`Just set ${namespaceElem.dataset.namespace} to ${enabled}`);
console.log(`avoidNamespaces is now ${avoidNamespaces}`);
}
}
function getMdDesc() {
let descString = `| Namespace | Tags |
| :--- | :--- |
`;
let namespaceElems = [...document.querySelector('#taglist > table > tbody').children].filter(
(tr) => !avoidNamespaces.some((namespace) => tr.textContent.includes(namespace))
);
for (const namespaceElem of namespaceElems) {
let namespace = namespaceElem.firstElementChild.innerText.split(':')[0];
descString += `| ${namespace} | `;
descString += [...namespaceElem.children[1].querySelectorAll('.gt a, .gtl a, a.tup')]
.map((tagElem) => {
let tag = tagElem.innerText;
tag = tag.split(' | ')[0];
return tag;
})
.join(', ');
descString += ` |\n`;
}
descString += `[Source](${document.URL})`;
return descString;
}
// copilot
function createElementFromHTML(text) {
const div = document.createElement('div');
div.innerHTML = text;
return div.firstElementChild;
}
// stackoverflow
function copyTextToClipboard(text) {
navigator.clipboard.writeText(text).then(
function () {
console.log('Async: Copying to clipboard was successful!');
console.log(`Copied\n${text}`);
},
function (err) {
console.error('Async: Could not copy text: ', err);
}
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment